EzPwnShellcode

示例
一个经典的x64PwnShellCode是:
1 | shellcode = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05" |
ShellCode解释
xor rdx, rdx
异或,将 rdx 置为0
mov rbx, 0x68732f6e69622f2f
将立即数 0x68732f6e69622f2f(小端字节序下”//bin/sh”的ASCII码)加载到寄存器 rbx 中
字符串
‘ / b i n / s h ‘
对应的ASCII值为:
0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68
shr rbx, 0x8
将寄存器 rbx 右移 8 位,即将 “//bin/sh/“ 字符串的地址向前偏移一个字节变为”/bin/sh”
push rbx
寄存器 rbx 中的值入栈,将 “/bin/sh” 字符串保存到栈上
mov rdi, rsp
将rsp 的值(即 “/bin/sh” 字符串的地址)复制给寄存器 rdi,将 rdi 设置为字符串的地址
push rax
rax 入栈
push rdi
rdi 入栈
mov rsi, rsp
将 rsi 设置为指向保存字符串地址的栈位置
mov al, 0x3b
将系统调用号 0x3b(十进制为 59)加载到 al
syscall
这条指令触发一个系统调用,具体的系统调用功能由 al 中的值决定。 al 的值为 59,这里执行的系统调用是执行一个程序,即执行 “/bin/sh”
因此,这段汇编代码的功能是执行一个系统调用,启动一个新的 shell 进程 (“/bin/sh”),进而GetShell
Tips
execve调用参数
在x86-64架构下系统调用号等于0x3b时对应的系统调用是execve,execve 是在 Unix 和类 Unix 的操作系统上运行新程序的操作系统系统调用
它的函数原型是:
1 | int execve(const char *filename, char *const argv[], char *const envp[]); |
- filename:这是你想要执行的程序的名称。
- argv:这是一个字符串数组,其中包含你要传递给该程序的参数。第一个参数,argv[0],通常是该程序的名称。
- envp:这也是一个字符串数组,其中每个字符串的形式为key=value,表示环境变量的设置。
在x86-64体系结构下,这三个参数分别通过 rdi、rsi 和 rdx 这三个寄存器来传递。所以在 syscall 调用前,需要先设置这三个寄存器,我们的EzPwnShellCode是这样构建一个execve调用的完整参数的:
- 首先将rdx寄存器清零,对应于execve的第三个参数envp,即没有设置任何环境变量。
- 然后将字符串’/bin/sh’逆序填入寄存器rbx,右移8位(即丢弃最后一个byte,也就是空字符’\0’),并压入栈。
- 将栈顶(也就是字符串’/bin/sh’的地址)移入rdi,对应于execve的第一个参数filename。
- 将rax(此时仍为0)和rdi(指向文件名的指针)压入栈,再将栈顶(指向一个包含文件名指针的数组的指针)移入rsi,对应于execve的第二个参数argv,即只有程序名本身一个参数。
- 最终执行syscall,进行调用。
rax入栈后并没有在后续代码中使用到,删除push rax这一步后程序的功能会发生改变吗
push rax 指令在这里是有用的。虽然后续的代码没有直接用到从 rax 寄存器push入栈的值(感谢你的观察!),但在 push rdi 之后,rsp 指针变化,指向了新的位置,即一个包含两个元素的数组的开头。这个数组的首元素就是通过 push rax 填充的0(因此 rax 的值在 syscall 调用前被设置为0),第二元素是要执行的程序的路径(’/bin/sh’)。而这个数组恰好符合 execve 系统调用的第2个参数 argv 的要求——包含要执行的程序名称的字符指针数组,并以NULL元素结束。所以,push rax的步骤是必要的。
如果删除 push rax 这一步,那么当 rsi 寄存器拿到的将只是 rdi 指向路径的地址,而不是一个合规的 argv 数组指针。这将导致参数传递出现问题,从而影响程序执行。所以,删除 push rax 这步会导致程序功能发生改变
32位的EzPwnShellCode(可以通过pwntools
的shellcraft.sh()
生成)
代码逻辑与x64相同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 /* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push b'/bin///sh\x00' */
push 0x68
push 0x732f2f2f
push 0x6e69622f
mov ebx, esp
/* push argument array ['sh\x00'] */
/* push 'sh\x00\x00' */
push 0x1010101
xor dword ptr [esp], 0x1016972
xor ecx, ecx
push ecx /* null terminate */
push 4
pop ecx
add ecx, esp
push ecx /* 'sh\x00' */
mov ecx, esp
xor edx, edx
/* call execve() */
push SYS_execve /* 0xb */
pop eax
int 0x80
- Title: EzPwnShellcode
- Author: 7erry
- Created at : 2023-09-21 00:00:00
- Updated at : 2023-09-21 00:00:00
- Link: http://7erry.com/2023/09/21/EzPwnShellcode/
- License: This work is licensed under CC BY-NC 4.0.