强网拟态初赛 部分wp
re
comeongo
函数名都没有混淆
修改部分函数的参数方便看
直接动调看相关参数
整体逻辑就都在check1和check2中
check1加密了username的前八位和password的前八位拼接起来
main_runtime_Encoding
base58码表
所以拿比较的base58直接解密即可得两者得前八位
username: GoM0bi13
password: G3tItEz
随便凑够16位 动调
在check2的函数中看到
有base64的enc
直接解
通过构建的特殊flag鉴别 能发现实际上是取了user的接下来4位和pass的接下来4位拼接
经过main_io_read的main_runtime_r1
做一个简单的ascii变换
其中非字母不变换
所以
import string
# cfFq
c = "_NubcfFq"
for tttt in c:
for ccc in string.ascii_letters:
t = 0
if ccc.isupper():
if ord(ccc) > ord("M"):
t = ord(ccc) - 12
else:
t = ord(ccc) + 12
if t == ord(tttt):
print(ccc)
elif ccc.islower():
if ord(ccc) > ord("m"):
t = ord(ccc) - 12
else:
t = ord(ccc) + 12
if t == ord(tttt):
print(ccc)
else:
print(ccc)
得到
B
Z
i
n
o
r
R
e
user可以是
_Bin
_Zin
pass为orRe
接着拼接进去
接着调
bytes_Compare 最后检验的是user的最后4位和pass的最后四位对应相加是否等于
main_runtime_other检测 相减是否是这几个值
from z3 import *
e = [0xDD, 0x8F, 0xA1, 0x64]
a = [Int(f"a[{i}]") for i in range(4)]
b = [Int(f"b[{i}]") for i in range(4)]
s = Solver()
for i in range(4):
s.add(a[i] + b[i] + i == e[i])
s.add(a[0] - b[0] == 15)
s.add(a[1] == b[1])
s.add(b[2] - a[2] == 63)
s.add(b[3] - a[3] == 31)
print(s.check())
f = s.model()
print(f)
for x in a:
print(chr(f[x].as_long()), end="")
print()
for x in b:
print(chr(f[x].as_long()), end="")
解出
vG0!
gGo@
所以
GoM0bi13_BinvG0!
G3tItEzorRegGo@
拼接套上flag md5即可
windowscall
要求长度为46
调试发现上面是md5函数 check转大写前后的md5是否相等 所以只有0-9A-F可以进入循环 小写a-f不行
findcrypt finger能发现有ecbaes函数 只加密了后32位 前八位是另外的约束
v42约束的是aes加密后的
T1 T2为前八位16进制的数
尝试不约束v57 只约束T1 T2
def f(start, end):
for i in range(start, end):
T2 = i & 0xffff
T1 = i >> 16
if ((T1 + 0x3800) & 0xffff <= 0x800) and ((T2 + 0x3500) & 0xffff <= 0x500) and (T2 - T1 == 0x2B8) and (
T2 & 0xff == 0xa0) and ((T1 & 0xFF00) < 0xCA00):
print(hex(i))
f(0, 0xffffffff + 1)
使用pypy3
就两个数 调整一下输入为flag{E8C9A0CC11111111111111111111111111111111}
直接在
拿key和iv
记得转成大写
flag{E8C9A0CC8B9854CDD0AC321B790FC74EFA520FBC}
indir
手动patch 俩小时
最后发现不用patch)
在sub402780发现虚拟机分发的地方
看到了有加减乘除ror rol的敏感操作
但是patch完之后调不了
在原文件下断
使用 gdb脚本
set pagination off
set args ./code
set $my=0
b *0x0004027A0
r
commands
silent
set $my=$my+1
continue
end
c
p $my
quit
通过下断到case分发处 判断执行了多少条指令
发现输入长度和指令条数无关
输入f
fl
fla
的指令条数一样
输入flag的执行条数最多 多于输入1111 判断出应该是每次判断一个int 如果不相等就直接结束
本来想侧信道 但是0xffffffff范围搭配上gdb开销太大
pintools开销也大
所以只能ida下断到ror和rol处
观察相关参数
总结脚本
from z3 import *
def ror(i, index):
return RotateRight(i, index)
def rol(i, index):
return RotateLeft(i, index)
flag = [BitVec(f"flag[{i}]", 32) for i in range(12)]
s = Solver()
s.add(flag[0] == 0x67616c66)
s.add(flag[0] - ror(flag[6], 6) == 0x95bfdeae)
s.add(rol(flag[9], 4) + flag[1] == 0x92a49991)
s.add(flag[2] == 0x68373177)
s.add(rol(flag[4], 3) + flag[3] == 0x7E09C2EA)
s.add(rol(flag[8], 10) + flag[4] == 0x1BF8EFC2)
s.add(flag[5] == 0X72625F37)
s.add(flag[6] - ror(flag[8], 2) == 0X8F47E1DD)
s.add(rol(flag[9], 12) + flag[7] == 0X9B914A92)
s.add(flag[8] == 0x646E315F)
s.add(flag[9] == 0X63337231)
s.add(flag[10] - ror(flag[11], 10) == 0X19633FDC)
s.add(flag[11] == 0x7D6C6C)
print(s.check())
from Crypto.Util.number import long_to_bytes
f = s.model()
for x in flag:
print(long_to_bytes(f[x].as_long())[::-1].decode(), end="")
# print(bytes(f[x].as_long()))
得到
flag{vm_w17h_1nd1r3c7_br4nch_4nd_1nd1r3c7_c4ll}
misc
babymisc
二分法查找即可
from pwn import *
while 1:
try:
io = remote("172.51.196.190", 9999)
a = io.recvline_endswith(b"start")
io.sendline(b"Y")
print(a)
wantsend0 = 500000
wantsend = str(wantsend0).zfill(6).encode()
io.sendline(wantsend)
a = io.recvline()
max = 999999
min = 0
while 1:
if a.endswith(b"low\n"):
min = wantsend0
wantsend0 = int((min + max) / 2)
wantsend = str(wantsend0).zfill(6).encode()
io.sendline(wantsend)
elif a.endswith(b":up\n"):
max = wantsend0
wantsend0 = int((min + max) / 2)
wantsend = str(wantsend0).zfill(6).encode()
io.sendline(wantsend)
else:
print("error")
a = io.recvline()
# print(a,wantsend0)
if b"flag" in a:
io.interactive()
except(EOFError):
pass