Loading

强网拟态初赛 部分wp

re

comeongo

函数名都没有混淆

修改部分函数的参数方便看

直接动调看相关参数

整体逻辑就都在check1和check2中

image-20221106161633354

check1加密了username的前八位和password的前八位拼接起来

main_runtime_Encoding

image-20221106161419221

image-20221106161433513

base58码表

所以拿比较的base58直接解密即可得两者得前八位

image-20221106161712441

username: GoM0bi13

password: G3tItEz

随便凑够16位 动调

在check2的函数中看到

image-20221106161938429

有base64的enc

直接解

image-20221106162015209

通过构建的特殊flag鉴别 能发现实际上是取了user的接下来4位和pass的接下来4位拼接

经过main_io_read的main_runtime_r1

image-20221106162225477

做一个简单的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

接着拼接进去

接着调

image-20221106162744008

bytes_Compare 最后检验的是user的最后4位和pass的最后四位对应相加是否等于image-20221106162834920

image-20221106163013065

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

image-20221106163325223

要求长度为46

image-20221106163342710

调试发现上面是md5函数 check转大写前后的md5是否相等 所以只有0-9A-F可以进入循环 小写a-f不行

findcrypt finger能发现有ecbaes函数 只加密了后32位 前八位是另外的约束

v42约束的是aes加密后的

T1 T2为前八位16进制的数

image-20221106163649402

image-20221106163721873

尝试不约束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

image-20221106163841247

就两个数 调整一下输入为flag{E8C9A0CC11111111111111111111111111111111}

直接在image-20221106164104308

拿key和iv

image-20221106164132498

image-20221106164147863

记得转成大写

image-20221106164309024

flag{E8C9A0CC8B9854CDD0AC321B790FC74EFA520FBC}

indir

手动patch 俩小时

image-20221106170330443

image-20221106164407482

最后发现不用patch)

在sub402780发现虚拟机分发的地方

image-20221106164737299

看到了有加减乘除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
posted @ 2022-11-16 14:44  FW_ltlly  阅读(128)  评论(0编辑  收藏  举报