【发布时间】:2023-03-26 20:56:01
【问题描述】:
我正在尝试编写一些 shell 代码,该代码将连接到 localhost 上端口 31337 上的侦听器,并发送程序的有效用户 ID 以用于学习目的。
为了使调试更容易,我构造了以下代码并用 nasm 组装:
BITS 32
section .data
section .bss
section .text
global _start:
_start:
; s = socket(2, 1, 0)
push BYTE 0x66 ; socketcall is syscall #102 (0x66).
pop eax
cdq ; Zero out edx for use as a null DWORD later.
xor ebx, ebx ; ebx is the type of socketcall.
inc ebx ; 1 = SYS_SOCKET = socket()
push edx ; Build arg array: { protocol = 0,
push BYTE 0x1 ; (in reverse) SOCK_STREAM = 1,
push BYTE 0x2 ; AF_INET = 2 }
mov ecx, esp ; ecx = ptr to argument array
int 0x80 ; After syscall, eax has socket file descriptor.
xchg esi, eax ; Save socket FD in esi for later.
; connect(s, [2, 31337, <IP address>], 16)
push BYTE 0x66 ; socketcall (syscall #102)
pop eax
inc ebx ; ebx = 2 (needed for AF_INET)
push DWORD 0x0100007f ; Build sockaddr struct: IP address = 127.0.0.1
push WORD 0x697a ; (in reverse order) PORT = 31337
push WORD bx ; AF_INET = 2
mov ecx, esp ; ecx = server struct pointer
push BYTE 16 ; argv: { sizeof(server struct) = 16,
push ecx ; server struct pointer,
push esi ; socket file descriptor }
mov ecx, esp ; ecx = argument array
inc ebx ; ebx = 3 = SYS_CONNECT = connect()
int 0x80
; geteuid(void)
push BYTE 0x31 ; call for geteuid (syscall #49)
pop eax
int 0x80 ; eax = effective user id
mov edi, eax ; store euid for later
; send(3, euid, 8, 0)
push BYTE 0x66 ; socketcall (syscall #102)
pop eax
xor edx, edx ; creating zero for flags
push edx
push BYTE 8 ; size of data to transmit
push edi ; euid
push esi ; file descriptor
mov ebx, 9 ; ebx = 9 = SYS_SEND = send()
mov ecx, esp ; argument array
int 0x80
; exit(1)
push BYTE 1 ; call for exit
pop eax
xor ebx, ebx
int 0x80
当我运行此代码时,成功创建了一个套接字并建立了与我在端口 31337 上侦听的服务器的连接。但是,我的用户 ID 没有发送。当我运行 strace 时,我收到以下输出:
execve("./connect_back", ["./connect_back"], [/* 18 vars */]) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(31337),
sin_addr=inet_addr("127.0.0.1")}, 16) = 0
geteuid() = 0
send(3, NULL, 8, 0) = -1 EFAULT (Bad address)
_exit(0) = ?
+++ exited with 0 +++
看来我的 euid 没有被用作参数。但是,当我在二进制文件上运行 gdb 时,程序似乎正确设置了发送调用的参数:
我是 nasm 新手,所以如果这是一个愚蠢的语法问题,我深表歉意。感谢您的帮助!
【问题讨论】:
-
很好的观察和愚蠢的错误!我以 root 身份运行 strace,结果为 NULL。以低权限用户重新运行 strace 清除了 NULL,然后我的 0x3e8 出现了,但它并没有解决错误的地址问题。
-
@Hosty:当然不是,正如迈克尔所说,
socketcall将它的参数放在内存中,第二个参数是指向缓冲区的 指针,而不是缓冲区本身. (奇怪的是send(2)手册页没有提到内核接口是一个通用的socketcall系统调用;大多数系统调用确实提到了库/内核的差异。我之前的评论(查看 ECX 的指针)是基于误解send是一个普通的系统调用,带有 ebx=fd、ecx=buf 等。 -
明白,谢谢!
标签: x86 nasm system-calls send