linux - 使用系统调用在程序集中保存 DNS 响应

标签 linux sockets assembly dns x86

所以我想了解更多关于 DNS 的知识,我想使用汇编来完成任务。

我在 tcpdump 中注意到我的请求似乎是准确的并且我收到了回复,但我的代码不知道如何处理这个。

我查看了一些网站,看起来应该使用 recvfrom,但我不明白如何调用该函数。我看到的另一个答案是使用 DUP2,据我所知,它会重定向 stdin,out 和 err 。根据我一直在阅读的内容,我应该操纵 sockcall (0x66) 来调用 recvfrom 并获取已发送给我的数据。大多数示例都使用 TCP,不太适合放在这里,因为我对 DNS 使用 UDP。

这是我在 google 上查询 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

最佳答案

这是它是如何完成的。

;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.. 

关于linux - 使用系统调用在程序集中保存 DNS 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55332406/

相关文章:

c++ - 如何解决pty master写slave读。主控写的数据主控也会读吗?

Java 套接字 - 丢失字节和 100% 处理器功耗

python - 你如何使用带 stunnel 的 Python 套接字?

string - 反转程序集 8086 中的字符串时出现问题

arrays - 在 ./parse_rss.pl 第 27 行的字符串 eq 中使用未初始化的值

c++ - 无法更改 CMake 中的默认链接器

linux - MDADM 暂停 Raid 重新同步以启用位图

c++ - 名称与类方法冲突

c - 整数加法中多余的中间存储指令

控制 GCC 优化