第四届“鹏城杯”联邦网络靶场协同攻防演练——RE部分wp
A1gorithms 发表于 安徽 CTF 544浏览 · 2024-11-10 08:38

joyVBS

vbs逆向,这题的算法其实不难,主要是看你怎么把用char表示的源码还原成常规格式的源码

使用vbsedit去打开转换一下

点击这个就可以转换成正常代码格式

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编码之后的结果进行了凯撒加密,随波逐流一把梭即可得到正确的base64编码的flag
fla被标准base编码应该是Zmxh


拿去解码然后给程序校检一下


flag{VB3_1s_S0_e1sY_4_u_r1gh3?btw_1t_iS_a1s0_Us3Fu1_a3D_1nTe3eSt1ng!}

Rafflesia

这题考察的是一个push pop call 永真跳转花指令和tls回调修改base64标准的表,然后base64的算法也被略微魔改了,多异或了个0x18。


很标准的永真跳转花
选中loc_4121EC按u将其转为未定义数据,然后nop掉它的第一个自己也就是0x89然后按c


这个是一个会影响栈帧平衡的花从call到retn全部nop掉


主函数的花就都被剔除了
然后找到函数头按p即可恢复函数


由于程序有tls和反调试,我们动调的话需要把断点打到tls回调函数那里,去绕过一些反调试


很明显tls里面也是有花的,和主函数的差不多,nop一下


IsDebuggerPresent这个反调有两种绕过的方法,一种则是动调的时候去改zf寄存器,还有一种就是对if判断下面的jz jnz进行更改,如果原来是jz,那我们就改成jnz,反之则相反

接下来把断点打到修改完表的地方进行调试提取即可


拿到码表
加密的base里面多异或了一个0x18

用cyberchef一把梭
注意一下转义字符把\ \换成\就可以了

RE5

这题主要考点是求余0异常处理,这个异常处理会修改key和tea算法里面sum的求值


在sub_401020里面可以看见生成随机数和初始化随机数种子的操作

这里就是更改tea算法里面sum取值的地方,idiv ecx触发就好跳到这里面来。
sum -= delta会变成
srand(0)
sum += rand()
动调看一下


这里的idiv ecx会修改key
之后跳到tea里面的idiv对key进行第二次修改


key就从1,2,3,4
变成了2,2,3,3
后面

这个异常会跳到获取生成随机数的地方,第一次调用会去执行srand(0)
不过要提前把断点打到sub_401020处,不如就直接执行完了


成功断住
第一次执行完srand(0),后面的每一次都是执行rand去获取随机数给sum去+


第一次生成的随机数是0x26,并且sum的值也是变成了0x26
说明sum的值实际是sum += rand()。
接下来编写解密脚本

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#define delta 0x61C88647
void Detea(uint32_t* e, int* key) {
    uint32_t v1, v2;
    int sum = 0;
    uint32_t randNum[64] = {};
    for (int i = 0; i < 32; i++) {

        randNum[i] = rand();
        //printf("0x%x,", randNum[i]);
    }
    v1 = e[0];
    v2 = e[1];
    for (int i = 0; i < 32; i++) {
        sum += randNum[i];
    }

    for (int i = 0; i < 32; ++i)
    {
        v2 -= (key[3] + (v1 >> 5)) ^ (sum + v1) ^ (key[2] + 16 * v1);
        v1 -= (key[1] + (v2 >> 5)) ^ (sum + v2) ^ (key[0] + 16 * v2);
        sum -= randNum[32 - i - 1];
    }
    e[0] = v1;
    e[1] = v2;
}



int main() {
    uint32_t enc[] = { 0xea2063f8, 0x8f66f252, 0x902a72ef, 0x411fda74, 0x19590d4d, 0xcae74317, 0x63870f3f, 0xd753ae61,0 };

    int key[] = { 2,2,3,3 };
    int index = 0;
    srand(0);


    for (index = 0; index < 4; index++) {
        Detea(&enc[index * 2], key);
    }
    puts((char*)&enc);
    return 0;
}


得到flag
d555ce75ec293c8ed232d83dffb0ff82

exec-pcb2024

这题把源码进行了数次base编码,然后通过exec去执行的,不过由于经过多次不同base编码最后得到的源码过大导致程序无法正常被exec调用
于是我手动解码拿到了最后的源码


最后得到的源码是这样的

a=True
d=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=d(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(k^s(z)+2)
 return R(n)
def E(s,parts_num):
 Q=d(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 d(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).hex())
 if U==['1796972c348bc4fe7a1930b833ff10a80ab281627731ab705dacacfef2e2804d74ab6bc19f60',2ea999141a8cc9e47975269340c177c726a8aa732953a66a6af183bcd9cec8464a']:
  Y('Congratulations! You got the flag!')
 else:
  Y('Wrong flag!')

很明显是一个rc4
只不过异或多+了个2
直接找一个标准的改一下然后解就好了
因为密文过长,所以得分两部分解


flag{thEn_I_Ca5_BE_YoUR_Onl7_ExeCUti6n_So_Use_m3_t0_R0n_tH17_Ex3Cuti0n}

class RC4:
    def __init__(self, key):
        self.key = key
        self.key_schedule()

    def key_schedule(self):
        """初始化密钥调度"""
        key_length = len(self.key)
        self.S = list(range(256))  # 初始化S盒,包含0到255
        j = 0
        # 根据密钥对S盒进行初始置换
        for i in range(256):
            j = (j + self.S[i] + self.key[i % key_length]) % 256
            self.S[i], self.S[j] = self.S[j], self.S[i]

    def keystream(self):
        """生成伪随机字节流"""
        i = j = 0
        while True:
            i = (i + 1) % 256
            j = (j + self.S[i]) % 256
            self.S[i], self.S[j] = self.S[j], self.S[i]
            k = self.S[(self.S[i] + self.S[j]) % 256]
            yield k

    def encrypt(self, plaintext):
        """加密函数"""
        plaintext_bytes = bytearray(plaintext, 'utf-8')
        keystream = self.keystream()
        ciphertext = bytearray()

        for byte in plaintext_bytes:
            ciphertext.append(byte ^ (next(keystream)+2))  # 异或操作

        return bytes(ciphertext)

    def decrypt(self, ciphertext):
        """解密函数"""
        keystream = self.keystream()
        plaintext = bytearray()

        for byte in ciphertext:
            plaintext.append(byte ^ (next(keystream)+2))  # 异或操作

        return bytes(plaintext)


# 测试RC4加密和解密
if __name__ == "__main__":
    # enc = "1796972c348bc4fe7a1930b833ff10a80ab281627731ab705dacacfef2e2804d74ab6bc19f60"
    enc = "2ea999141a8cc9e47975269340c177c726a8aa732953a66a6af183bcd9cec8464a"
    key = b"v3ry_s3cr3t_p@ssw0rd"  # 密钥
    rc4 = RC4(key)
    # enc = "2ea999141a8cc9e47975269340c177c726a8aa732953a66a6af183bcd9cec8464a"
    ciphertext = bytes.fromhex(enc)
    #
    decrypted_text = rc4.decrypt(ciphertext)
    print(f"解密后的文本: {decrypted_text}")
附件:
2 条评论
某人
表情
可输入 255
目录