分类 鹏城杯 下的文章

minire

有个elf的upx,随便找了个脱壳教程
https://blog.csdn.net/m0_49936845/article/details/119976496

main函数
2024-11-09T14:18:27.png

下面的else是假的,你需要手动传第一个参数是root才会进第一个条件。(顺便提一下,fake的flag是fksdde7039,MD5爆破出的)

然后去real里面,是一个真正让你输入的地方,不过只是输出了input:,真正的逻辑在下面那个函数。
但是核心函数基本无法直接反编译,我们直接看汇编吧。
2024-11-09T14:19:56.png

经典的VM(Handler + Dispatcher)
2024-11-09T14:20:26.png
我们可以找到一个getchar sub_402907然后就可以不断进行硬件断点跟数据了

注意这一块
2024-11-09T14:21:30.png

稍微分析一下
2024-11-09T14:22:16.png
2024-11-09T14:22:41.png
2024-11-09T14:22:59.png

然后我们下断点
2024-11-09T14:23:19.png
进行条件断点,打印值
2024-11-09T14:23:25.png

这样我们就trace了vm

x[0]^=4
x[0]+=12
x[0]^=11
x[0]^=12
x[0]-=2
x[0]-=1
x[0]^=6
x[1]+=10
x[1]^=12
x[1]+=5
x[2]+=4
x[2]+=14
x[3]-=10
x[3]-=3
x[3]+=13
x[3]+=7
x[3]-=9
x[3]^=14
x[4]-=7
x[4]-=15
x[5]^=14
x[6]^=2
x[6]+=0
x[6]^=2
x[6]+=9
x[6]+=3
x[6]-=2
x[6]+=13
x[6]^=1
x[7]+=8
x[7]+=12
x[7]^=15
x[7]+=5
x[7]^=3
x[7]+=8
x[8]+=8
x[8]+=2
x[8]^=8
x[8]-=12
x[8]+=11
x[8]-=3
x[8]^=9
x[8]-=2
x[8]+=8
x[9]-=0
x[9]-=2
x[10]+=11
x[11]-=2
x[11]^=7
x[11]-=1
x[11]-=5
x[12]+=1
x[12]-=13
x[12]+=12
x[13]-=2
x[13]-=14
x[13]-=9
x[13]^=14
x[13]+=1
x[13]+=10
x[13]-=7
x[13]-=1
x[13]+=9
x[14]-=0
x[14]-=11
x[14]^=4
x[14]+=9
x[15]^=14
x[15]+=5
x[15]-=12
x[15]-=4
x[15]-=4
x[15]+=15
x[15]+=14
x[15]-=4
x[15]^=5
x[15]-=12
x[16]^=11
x[16]+=13
x[16]-=11
x[16]^=4
x[16]+=10
x[16]-=8
x[17]+=10
x[17]+=15
x[17]+=2
x[17]-=6
x[17]-=9
x[17]-=9
x[17]+=3
x[17]+=5
x[17]-=15
x[17]+=2
x[18]-=14
x[18]-=13
x[19]^=7
x[19]-=15
x[19]-=1
x[19]^=3
x[19]-=3
x[19]+=11
x[19]+=10
x[19]+=10
x[20]+=8
x[20]-=6
x[20]-=7
x[20]^=4
x[20]-=1
x[20]^=3
x[21]+=5
x[21]+=2
x[21]+=10
x[21]^=0
x[22]-=7
x[22]+=0
x[22]+=8
x[22]+=1
x[22]+=1
x[22]^=10
x[22]-=14
x[22]^=15
x[22]-=7
x[22]^=8
x[23]^=4
x[23]-=9
x[23]+=15
x[24]+=12
x[24]^=2
x[24]^=4
x[24]-=7
x[24]+=1
x[25]+=0
x[25]+=9
x[25]^=2
x[25]+=14
x[25]^=11
x[25]^=1
x[25]+=2
x[25]+=9
x[25]-=9
x[26]+=6
x[27]^=10
x[27]-=4
x[27]-=13
x[27]^=8
x[27]-=14
x[27]+=14
x[27]^=14
x[28]+=1
x[28]^=4
x[28]-=9
x[28]+=9
x[28]-=5
x[28]+=13
x[28]+=1
x[28]^=10
x[29]^=9
x[30]+=14
x[30]+=12
x[30]^=0
x[30]-=0
x[30]-=15
x[30]^=11
x[30]-=11
x[30]+=8
x[31]+=11
x[31]+=6
x[31]+=1
x[31]^=12
x[31]-=6
x[31]-=14
x[32]-=11
x[32]^=13
x[32]+=5
x[32]^=2
x[32]-=2
x[33]+=13
x[33]^=6
x[33]+=15
x[33]^=0
x[33]-=3
x[33]-=12
x[33]-=15
x[33]^=11
x[34]+=9
x[34]+=10
x[34]+=10
x[34]^=10
x[35]-=13
x[36]^=7
x[36]-=0
x[37]-=11
x[37]+=14
x[37]-=8
x[37]+=4
x[37]+=3
x[37]+=13
x[37]^=3
x[37]^=10

在这之后,我们需要寻找enc(标准加密值)
我们在vm_readByte处下断,然后我们就可以看到enc不断浮现在我们眼前。
最后脚本一把梭

from regadgets import *
from z3 import *
from copy import deepcopy
x = [BitVec(f"x{i}", 8) for i in range(38)]
y = deepcopy(x)

x[0]^=4
x[0]+=12
x[0]^=11
x[0]^=12
x[0]-=2
x[0]-=1
x[0]^=6
x[1]+=10
x[1]^=12
x[1]+=5
x[2]+=4
x[2]+=14
x[3]-=10
x[3]-=3
x[3]+=13
x[3]+=7
x[3]-=9
x[3]^=14
x[4]-=7
x[4]-=15
x[5]^=14
x[6]^=2
x[6]+=0
x[6]^=2
x[6]+=9
x[6]+=3
x[6]-=2
x[6]+=13
x[6]^=1
x[7]+=8
x[7]+=12
x[7]^=15
x[7]+=5
x[7]^=3
x[7]+=8
x[8]+=8
x[8]+=2
x[8]^=8
x[8]-=12
x[8]+=11
x[8]-=3
x[8]^=9
x[8]-=2
x[8]+=8
x[9]-=0
x[9]-=2
x[10]+=11
x[11]-=2
x[11]^=7
x[11]-=1
x[11]-=5
x[12]+=1
x[12]-=13
x[12]+=12
x[13]-=2
x[13]-=14
x[13]-=9
x[13]^=14
x[13]+=1
x[13]+=10
x[13]-=7
x[13]-=1
x[13]+=9
x[14]-=0
x[14]-=11
x[14]^=4
x[14]+=9
x[15]^=14
x[15]+=5
x[15]-=12
x[15]-=4
x[15]-=4
x[15]+=15
x[15]+=14
x[15]-=4
x[15]^=5
x[15]-=12
x[16]^=11
x[16]+=13
x[16]-=11
x[16]^=4
x[16]+=10
x[16]-=8
x[17]+=10
x[17]+=15
x[17]+=2
x[17]-=6
x[17]-=9
x[17]-=9
x[17]+=3
x[17]+=5
x[17]-=15
x[17]+=2
x[18]-=14
x[18]-=13
x[19]^=7
x[19]-=15
x[19]-=1
x[19]^=3
x[19]-=3
x[19]+=11
x[19]+=10
x[19]+=10
x[20]+=8
x[20]-=6
x[20]-=7
x[20]^=4
x[20]-=1
x[20]^=3
x[21]+=5
x[21]+=2
x[21]+=10
x[21]^=0
x[22]-=7
x[22]+=0
x[22]+=8
x[22]+=1
x[22]+=1
x[22]^=10
x[22]-=14
x[22]^=15
x[22]-=7
x[22]^=8
x[23]^=4
x[23]-=9
x[23]+=15
x[24]+=12
x[24]^=2
x[24]^=4
x[24]-=7
x[24]+=1
x[25]+=0
x[25]+=9
x[25]^=2
x[25]+=14
x[25]^=11
x[25]^=1
x[25]+=2
x[25]+=9
x[25]-=9
x[26]+=6
x[27]^=10
x[27]-=4
x[27]-=13
x[27]^=8
x[27]-=14
x[27]+=14
x[27]^=14
x[28]+=1
x[28]^=4
x[28]-=9
x[28]+=9
x[28]-=5
x[28]+=13
x[28]+=1
x[28]^=10
x[29]^=9
x[30]+=14
x[30]+=12
x[30]^=0
x[30]-=0
x[30]-=15
x[30]^=11
x[30]-=11
x[30]+=8
x[31]+=11
x[31]+=6
x[31]+=1
x[31]^=12
x[31]-=6
x[31]-=14
x[32]-=11
x[32]^=13
x[32]+=5
x[32]^=2
x[32]-=2
x[33]+=13
x[33]^=6
x[33]+=15
x[33]^=0
x[33]-=3
x[33]-=12
x[33]-=15
x[33]^=11
x[34]+=9
x[34]+=10
x[34]+=10
x[34]^=10
x[35]-=13
x[36]^=7
x[36]-=0
x[37]-=11
x[37]+=14
x[37]-=8
x[37]+=4
x[37]+=3
x[37]+=13
x[37]^=3
x[37]^=10

s = Solver()
enc = [0x60, 0x7F, 0x73, 0x6B, 0x65, 0x4F, 0x80, 0x5D, 0x64, 0x50, 0x64, 0x2C, 0x37, 0x33, 0x5C, 0x74, 0x45, 0x65, 0x55, 0x60, 0x4A, 0x84, 0x6E, 0x50, 0x7F, 0x58, 0x5F, 0x27, 0x7F, 0x5A, 0x8C, 0x6B, 0x62, 0x60, 0x59, 0x59, 0x45, 0x85]

for i in range(len(x)):
    s.add(enc[i] == x[i])
for m in z3_get_models(s):
    print(m)
    for i in y:
        print(chr(m[i].as_long()), end='')
    print('')
# flag{AjJIRY77BbuNgpPSswNwCY8gSyawo6fB}

joyVBS

纯送分题
https://www.onlinegdb.com/online_vb_compiler
print出来代码

assembly 'a, Version=0.0, Culture=neutral, PublicKeyToken=null' saved successfully to '/home/a.out'.
Compilation successful
Compilation took 00:00:00.7942080
MsgBox "VBScript, often abbreviated as VBS, is an event-driven programming language developed by Microsoft, primarily used for scripting in the Windows environment."
MsgBox "It is based on the Visual Basic programming language and is designed to be simple and easy to use, especially for those familiar with the BASIC programming language."
MsgBox "And for me, it is the first programming language that I've leart"
MsgBox "Hackers! Have fun with this VBS challenge!"
flag = InputBox("Enter the FLAG:", "Hack for fun")
wefbuwiue = "NalvN3hKExBtALBtInPtNHTnKJ80L3JtqxTboRA/MbF3LnT0L2zHL2SlqnPtJLAnFbIlL2SnFT8lpzFzA2JHrRTiNmT9"

qwfe = 9+2+2+1

Function Base64Decode(base64EncodedString)
    Dim xml, elem
    Set xml = CreateObject("MSXML2.DOMDocument")
    Set elem = xml.createElement("tmp")
    elem.dataType = "bin.base64" 
    elem.text = base64EncodedString 
    Dim stream
    Set stream = CreateObject("ADODB.Stream")
    stream.Type = 1 'Binary
    stream.Open
    stream.Write elem.nodeTypedValue 
    stream.Position = 0
    stream.Type = 2 'Text
    stream.Charset = "utf-8"
    Base64Decode = stream.ReadText
    stream.Close
End Function
Function Caesar(str,offset)
        Dim length,char,i
        Caesar = ""
        length = Len(str)
        For i = 1 To length
                char = Mid(str,i,1)
                If char >= "A" And char <= "Z" Then
                        char = Asc("A") + (Asc(char) - Asc("A") + offset) Mod 26
                        Caesar = Caesar & Chr(char)
                ElseIf char >= "a" And char <= "z" Then
                        char = Asc("a") + (Asc(char) - Asc("a") + offset) Mod 26
                        Caesar = Caesar & Chr(char)
                Else
                        Caesar = Caesar & char
                End If
        Next
End Function

If flag = Base64Decode(Caesar(wefbuwiue, 26-qwfe)) Then
    MsgBox "Congratulations! Correct  FLAG!"
Else
    MsgBox "Wrong flag."
End If

凯撒加密+base64
2024-11-09T14:26:36.png
flag{VB3_1s_S0_e1sY_4_u_r1gh3?btw_1t_iS_a1s0_Us3Fu1_a3D_1nTe3eSt1ng!}

exec

Python Function Hook

import base64
hook_exec = exec
def my_exec(x):
    print('myexec', x)
    hook_exec(x)
exec = my_exec
...

这样就能拿到每次exec的代码,从而得到


a=True
len=len
G=list
g=range
s=next
R=bytes
o=input
Y=print
def l(S):
 i=0
 j=0
 while a:
  i=(i+1)%256
  j=(j+S[i])%256
  S[i],S[j]=S[j],S[i]
  K=S[(S[i]+S[j])%256]
  yield K
def N(key,O):
 I=len(key)
 S=G(g(256))
 j=0
 for i in g(256):
  j=(j+S[i]+key[i%I])%256
  S[i],S[j]=S[j],S[i]
 z=l(S)
 n=[]
 for k in O:
  n.append(s(z)+2)
 return bytes(n).hex()
def E(s,parts_num):
 Q=len(s.decode())
 S=Q//parts_num
 u=Q%parts_num
 W=[]
 j=0
 for i in g(parts_num):
  T=j+S
  if u>0:
   T+=1
   u-=1
  W.append(s[j:T])
  j=T
 return W
if __name__=='__main__':
 L=o('input the flag: >>> ').encode()
 assert len(L)%2==0,'flag length should be even'
 t=b'v3ry_s3cr3t_p@ssw0rd'
 O=E(L,2)
 U=[]
 for i in O:
  U.append(N(t,i))
 print(U)
 if U==['1796972c348bc4fe7a1930b833ff10a80ab281627731ab705dacacfef2e2804d74ab6bc19f60','2ea999141a8cc9e47975269340c177c726a8aa732953a66a6af183bcd9cec8464a']:
  Y('Congratulations! You got the flag!')
 else:
  Y('Wrong flag!')

无法直接运行是因为U的第二个少了个',补上就行,上面代码我稍微改了一下,输出魔改rc4的keystream
然后直接解就行
2024-11-09T14:27:19.png
flag{thEn_I_Ca5_BE_YoUR_Onl7_ExeCUti6n_So_Use_m3_t0_R0n_tH17_Ex3Cuti0n}

RE5

异常处理改了tea的key,每一轮的sum值是由srand(0),每次取随机数相加得到的,然后直接解标准tea即可。

from regadgets import *
from typing import List, Tuple, Union
from ctypes import c_uint32
rng = WindowsRand(0)
def tea_decrypt_plus(
    src: Union[Tuple[int, int], bytes, List[int]], key: Union[List[int], bytes], delta: int = 0x9E3779B9, rounds: int = 32
) -> Union[Tuple[int, int], bytes, List[int]]:
    if type(src) == bytes:
        result = b''
        for i in pack_dword(byte2dword(src)):
            result += dword2byte(tea_decrypt_plus(i, key, delta, rounds))
        return result
    elif type(src) == list:
        result = b''
        for i in pack_dword(src):
            result += dword2byte(tea_decrypt_plus(i, key, delta, rounds))
        return result
    elif type(src) != tuple:
        raise "wrong src type"
    # For bytes key
    _rands = rng.rands(32)
    if type(key) == bytes:
        key = byte2dword(key)
    elif type(key) != list:
        raise "wrong key type"
    l, r = c_uint32(src[0]), c_uint32(src[1])
    _sum = c_uint32(sum(_rands))
    k = [c_uint32(i) for i in key]
    for i in range(rounds):
        r.value -= (
            ((l.value << 4) + k[2].value)
            ^ (l.value + _sum.value)
            ^ ((l.value >> 5) + k[3].value)
        )
        l.value -= (
            ((r.value << 4) + k[0].value)
            ^ (r.value + _sum.value)
            ^ ((r.value >> 5) + k[1].value)
        )
        _sum.value -= _rands[rounds - i - 1]
    return (l.value, r.value)

enc = b"\xF8\x63\x20\xEA\x52\xF2\x66\x8F\xEF\x72\x2A\x90\x74\xDA\x1F\x41\x4D\x0D\x59\x19\x17\x43\xE7\xCA\x3F\x0F\x87\x63\x61\xAE\x53\xD7\x22\x3D\x43\x4D\xDD\xC2\xBC\xB2\xFF\xFF\xFF\xFF\x01\x00\x00\x00\x2F\x00\x00\x00\x01\x00\x00\x00\x66\x6C\x61\x67\x7B\x31\x32\x33\x31\x34\x31\x32\x33\x34\x31\x32\x34\x31\x32\x34\x32\x31\x33\x34\x31\x32\x33\x34\x31\x32\x33\x31\x32\x34\x33\x32\x33\x7D\x00\x00\x39\xDC\xE1\x2E\xF1\xEA\xD6\x40\x9A\x76\x29\x5E\x17\xB6\xF4\x38\xD0\x14\xF5\x8C\xA2\x7E\xEB\xBE\xD5\xFA\xBD\x18\xBF\x05\x97\x49"
# enc = b"\x9A\x76\x29\x5E\x17\xB6\xF4\x38"
# enc = b"\x39\xDC\xE1\x2E\xF1\xEA\xD6\x40"
enc = byte2dword(enc)

# print(tea_decrypt(enc, key=[2,2,3,4]))
print(tea_decrypt_plus(enc, key=[2,2,3,3]))

flag{d555ce75ec293c8ed232d83dffb0ff82} 三血

BigTea

唯一的一血,全程黑箱trace+猜的,控制流混淆太恶心了
Xor Trace,有小数字(0~3的xor),对应xxtea的key[(p & 3) ^ e] ^ z,所以直接认为是xxtea

1287150135 = 858927483 ^ 2139777868
3 = 3 ^ 0
3083858674 = 2100375857 ^ 3405693891
3475065957 = 3435709932 ^ 65636745
3581236543 = 3541242640 ^ 107365935
2686381197 = 76041513 ^ 2761335204
1270372984 = 875704628 ^ 2139777868
2 = 3 ^ 1
.....
2296010693 = 1761772981 ^ 3789083248
3006293146 = 1572571602 ^ 4002147656
0 = 2 ^ 2
1724993655 = 425409339 ^ 2139777868
1982135953 = 1995319112 ^ 13294041
2651112074 = 2511582128 ^ 196571450
237532170 = 436319505 ^ 338280731
3939128127 = 71417463 ^ 4002147656
1 = 2 ^ 3
2522458527 = 141479974 ^ 2654435769
289771357 = 285669852 ^ 4421249
2254779822 = 2263679584 ^ 8927182
378091989 = 2166619358 ^ 2544551179

我们慢慢分析,XXTEA的key,可以从Trace里面盯出来,前面异或算出来的是索引值,所以我们很容易就能拿到四个key,然后我们输入11112222作为待加密数据,由于xxtea的特性,z==y,那么我们很方便的可以看到下面四个值在trace中的样子,然后可以倒推出delta = 0x70D7D4CC

Ly = y.value << 2
Ry = y.value >> 3
Lz = z.value << 4
Rz = z.value >> 5 
keys
0x7f8a6b4c
0x9e3779b9
0xdeafbeef
0xcafec3c3

2024-11-09T14:28:46.png
然后,我们可以使用自己的xxtea加密数据,发现我们的加密数据只在trace的中间,而不是最后,说明加密可能不只一轮或者是xxtea魔改轮数,经过测试是后者,通过fuzz,我们可以知道魔改是 6 + 52//n -> 32 + 52 // n,我们抄出来就行了,最后至于找enc,是通过在最后一轮对于密文下断,然后在程序内存中搜索第一个加密的,进行硬件断点,然后跑,就可以找到cmp。
2024-11-09T14:29:18.png
然后
2024-11-09T14:29:27.png
我们可以观察到下面对cl进行的操作,cl如果不为0则两段密文不一样,我们每次运行打断点手动置0,然后输入很长的input,就可以拿到所有的对比值

cmp 673017408,   1214171175
cmp 3365566770,  3066933611
cmp 1583712898,  4062421290
cmp 1719532837,  3922368852
cmp 2253378100,  2540993788
cmp 1994934834,  1332676358
cmp 4110442914,  22469667
cmp 4185531028,  3633624522
cmp 1279845426,  2241914041
cmp 1481920662,  3542748258
cmp 725179328,   1546291565

最后,使用regadgets库(由于还在开发,小范围测试,所以把库内的代码都复制了出来)进行解密。即可。

from typing import List, Union
from ctypes import c_uint32

def xxtea_std_shift(z, y, sum, k, p, debug = False):
    if debug:
        print("-----------------XXTEA_STD_SHIFT-----------------")
    e = (sum.value >> 2) & 3
    PE = (p & 3) ^ e
    Ly = y.value << 2
    Ry = y.value >> 3
    Lz = z.value << 4
    Rz = z.value >> 5 

    LzRy = Rz ^ Ly
    LyRz = Ry ^ Lz
    SY = sum.value ^ y.value
    K = k[PE].value
    KZ = K ^ z.value
    result = (LzRy + LyRz) ^ (KZ + SY)
    if debug:
        print("sum = ", hex(sum.value))
        print("e   = ", hex(e))
        print("PE  = ", hex(PE))
        print("SY  = ", hex(SY))
        print("z   = ", hex(z.value))
        print("y   = ", hex(y.value))
        print("Ly  = ", hex(Ly))
        print("Ry  = ", hex(Ry))
        print("Lz  = ", hex(Lz))
        print("Rz  = ", hex(Rz))
        print("LzRy= ", hex(LzRy & 0xffffffff))
        print("LyRz= ", hex(LyRz & 0xffffffff))
        print("K   = ", hex(K))
        print("KZ  = ", hex(KZ))
        print("ret = ", hex(result & 0xffffffff))
        print("-----------------XXTEA_STD_SHIFT-----------------")
    return result

def xxtea_decrypt(
    src: Union[List[int], bytes],
    key: List[int],
    delta: int = 0x9E3779B9,
    round_base: int = 6,
    round_addi: int = 52,
    shift_func=xxtea_std_shift,
    debug=False,
) -> Union[List[int], bytes]:
    in_bytes = False
    if type(src) == bytes:
        src = byte2dword(src)
        in_bytes = True
    if type(key) == bytes:
        key = byte2dword(key)
    if in_bytes:
        return dword2byte(xxtea_decrypt(src, key, delta, round_base, round_addi, shift_func, debug))
    src = [c_uint32(i) for i in src]
    key = [c_uint32(i) for i in key]
    sum, e, y = c_uint32(0), c_uint32(0), c_uint32(0)
    delta = c_uint32(delta)
    n = len(src)
    rounds = round_base + round_addi // n
    sum.value = rounds * delta.value
    y = src[0]
    for _ in range(rounds):
        for p in range(n - 1, 0, -1):
            z = src[p - 1]
            shift_result = shift_func(z, y, sum, key, p, debug)
            src[p].value -= shift_result 
            y = src[p]
        p -= 1
        z = src[n - 1]
        shift_result = shift_func(z, y, sum, key, p, debug)
        src[0].value -= shift_result
        y = src[0]
        sum.value -= delta.value
    return [i.value for i in src]


enc = [1214171175,3066933611,4062421290,3922368852,2540993788,1332676358,22469667,3633624522,2241914041,3542748258,1546291565]
enc = xxtea_decrypt(enc, key=[0x7f8a6b4c, 0x9e3779b9, 0xdeafbeef, 0xcafec3c3],delta=0x7f8a6b4c, round_base=32)
print(dword2byte(enc))
# b'flag{9aad3962-8ad5-48d0-83dc-1e60a81439a1}\x00\x00'

Rafflesia

动态调试,有反调试,直接用ScyllaHide过掉。
base64换表,base64稍微改了一下:最后xor了0x18
最后在memcmp下断拿密文就行
2024-11-09T14:30:14.png

FlvtterM

Blutter逆向
然后就没时间做了,看到个换表base58,前面有一个x[i+1] ^= x[i]和一个换位置,但是最前面还有一个SBox相关的操作,SBox这个没看出来是什么。