Saving DNS response in assembly using syscalls

0

So I am wanting to learn more about DNS and I am wanting to use assembly to accomplish the task.

I noticed in tcpdump that my request appears to be accurate and I receive a response back, but my code doesn't know how to handle this.

I looked on a few sites and it looks like a recvfrom should be used , but I don't understand how I would call that function. Another answer I see is to use DUP2 and from what I understand it redirects stdin,out and err . From what I have been reading , I should manipulate sockcall ( 0x66 ) to call the recvfrom and get the data that has been sent to me. Most of the examples are using TCP and don't quite fit here since I am using UDP for the DNS.

Here is my code which queries google for example.com

nop
nop
nop
nop

; we create a socket fd, using again syscall 0x66 and argument SYS_SOCKET so ebx = 1  
push   0x66
pop    eax
push   0x1 
pop    ebx
xor    ecx,ecx
push   ecx
; but this times it will be a SOCK_DGRAM UDP, so 0x2 as argument 
push   0x2  
push   0x2 
mov    ecx,esp
int    0x80
; saving fd 
push 0x08080808 ; 8.8.8.8 ; I love that this doesn't really need to be backwards.
;push 0x0100007F            ; 0100007F 1.0.0.127 for testing...

xor edx,edx
mov dh, 0x35  ; port 53; comment this for variable port 
push dx       ; comment this for variable port 
              ;  push word PORT ; UNcomment this for variable port 
push word 0x2 ; 

mov ecx,esp   ; save pointer to ecx 
push 0x10     ; addrlen 
push ecx      ; pointer to sockaddr 
push eax      ; fd received previously 
mov ecx,esp   ;  
mov esi,eax   ; save fd for next call 
xor eax,eax 
mov al,0x66  
add bl,0x2   
int 0x80


    ; now we send a UDP packet to open stateful firewall :] 
xor eax,eax
mov al,0x66  ; ssize_t send(int sockfd, const void *buf, size_t len, int flags);
push 0x00000001       
push 0x00010000
push 0x6d6f6303
push 0x656c706d
push 0x61786507
push 0x00000000
push 0x00000100
push 0x0001AAAA


mov edx,esp ; Move the string to EDX so we can send it. 
xor ecx,ecx
push ecx  
push 64 ; size of message to be sent is 8
push edx 
push esi 
mov ecx,esp
xor ebx,ebx 
mov bl,0x9 
int 0x80 


mov ebx,esi
xor ecx,ecx
mov cl,0x2

loop:   ;Not sure if this is needed at all
; syscall dup2 
mov    al,0x3f
int    0x80
dec    ecx
jns loop

xor esi,esi
push   esi 
mov    edx,esp
push   ebx
mov    ecx,esp
int    0x80
nop
nop
nop
linux
sockets
assembly
dns
x86
asked on Stack Overflow Mar 25, 2019 by LUser • edited Mar 25, 2019 by Peter Cordes

1 Answer

0

Here is how it's done .

;Author : Krash

section     .text
global      main   ;must be declared for linker (ld)




; SOCKETCALL PARAMS You can pass a value to EBX to utilize one of these functions. 

; #define SYS_SOCKET      1               /* sys_socket(2)                */
; #define SYS_BIND        2               /* sys_bind(2)                  */
; #define SYS_CONNECT     3               /* sys_connect(2)               */
; #define SYS_LISTEN      4               /* sys_listen(2)                */
; #define SYS_ACCEPT      5               /* sys_accept(2)                */
; #define SYS_GETSOCKNAME 6               /* sys_getsockname(2)           */
; #define SYS_GETPEERNAME 7               /* sys_getpeername(2)           */
; #define SYS_SOCKETPAIR  8               /* sys_socketpair(2)            */
; #define SYS_SEND        9               /* sys_send(2)                  */
; #define SYS_RECV        10              /* sys_recv(2)                  */
; #define SYS_SENDTO      11              /* sys_sendto(2)                */
; #define SYS_RECVFROM    12              /* sys_recvfrom(2)              */
; #define SYS_SHUTDOWN    13              /* sys_shutdown(2)              */
; #define SYS_SETSOCKOPT  14              /* sys_setsockopt(2)            */
; #define SYS_GETSOCKOPT  15              /* sys_getsockopt(2)            */
; #define SYS_SENDMSG     16              /* sys_sendmsg(2)               */
; #define SYS_RECVMSG     17              /* sys_recvmsg(2)               */
; #define SYS_ACCEPT4     18              /* sys_accept4(2)               */
; #define SYS_RECVMMSG    19              /* sys_recvmmsg(2)              */
; #define SYS_SENDMMSG    20              /* sys_sendmmsg(2)              */


;The Message We want to send.



   ;DNS HEADER;
   ; AA AA - ID
   ; 01 00 - Query parameters
   ; 00 01 - Number of questions
   ; 00 00 - Number of answers
   ; 00 00 - Number of authority records
   ; 00 00 - Number of additional records
   ; DNS QUESTION --
   ; 07 - 'example' has length 7, ;so change this to be the length of domain ; keep in mind there are not '.' in the question.
   ; 65 - e
   ; 78 - x
   ; 61 - a
   ; 6D - m
   ; 70 - p
   ; 6C - l
   ; 65 - e

   ; 03 - subdomain '.com'  length 03  ; change this to be the length of type.

   ; 63 - c
   ; 6F - o
   ; 6D - m

   ; 00    - zero byte to end the QNAME 
   ; 00 01 - QTYPE 
   ; 00 01 - QCLASS




   ; DNS ANSWER! This is What We Want to receive ;
   ; aa aa
   ; 81 80
   ; 00 01
   ; 00 01
   ; 00 00
   ; 00 00
   ; 07 65
   ; 78 61
   ; 6d 70
   ; 6c 65
   ; 03 63
   ; 6f 6d
   ; 00 00
   ; 01 00
   ; 01 c0
   ; 0c 00
   ; 01 00
   ; 01 00
   ; 00 12
   ; 8d 00
   ; 04 

   ; IP ADDRESS IN HEX -- 93.184.216.34
   ; 5d
   ; b8 
   ; d8
   ; 22



main:                                         
    ; we create a socket fd, using again syscall 0x66 and argument SYS_SOCKET so ebx = 1  
    push   0x66
    pop    eax
    push   0x1 
    pop    ebx
    xor    ecx,ecx
    push   ecx
    ; but this times it will be a SOCK_DGRAM UDP, so 0x2 as argument 
    push   0x2  
    push   0x2 
    mov    ecx,esp
    int    0x80 ; SYS_SOCKET
    ; saving fd on the stack ; In reality I think I will save the port here instead 
    push eax


    push 0x08080808 ; 8.8.8.8 ; I love that this doesn't really need to be backwards.
    ;push 0x0100007F            ; 0100007F 1.0.0.127 for testing...

    xor edx,edx
    mov dh, 0x35  ; port 53; comment this for variable port 
    push dx       ; comment this for variable port 
                  ; push word PORT ; UNcomment this for variable port 
    push word 0x2 ; 




    mov ecx,esp   ; save pointer to ecx 
    push 0x10     ; addrlen 
    push ecx      ; pointer to sockaddr 
    push eax      ; fd received previously 
    mov ecx,esp   ;  
    mov esi,eax   ; save fd for next call 
    xor eax,eax 
    mov al,0x66  
    add bl,0x2   ; BL  = 3 SYS_CONNECT
    int 0x80      ;CALL  SYS_CONNECT


    ; now we send a UDP packet to open stateful firewall :] 
    xor eax,eax
    mov al,0x66   

     push 0x00000001 ; Origional Working request to google dns for example.com
     push 0x00010000
     push 0x6d6f6303
     push 0x656c706d
     push 0x61786507  
     push 0x00000000
     push 0x00000100
     push 0x0001AAAA   ; This is the DNS HEADER above in little endian order.


    mov edx,esp ; Move the string to EDX so we can send it. 
    xor ecx,ecx
    push ecx  
    push 64 ; size of message to be sent is 8
    push edx 
    push esi 
    mov ecx,esp
    xor ebx,ebx 
    mov bl,0x9 
    int 0x80     ;CALL SYS_SEND

    mov eax,  3 ; Prepare for SYSCALL_READ
    mov ebx,  3 ; 
    mov ecx, esp
    mov edx, 100
    int 0x80   ;CALL SYSCALL_READ

    add esp, eax
    sub esp, 4 
    mov eax ,[esp]
    push eax ; Probably not needed, I just want to ensure it's saved on the stack for further use.. 
answered on Stack Overflow Apr 1, 2019 by LUser • edited Apr 7, 2019 by LUser

User contributions licensed under CC BY-SA 3.0