羊城杯Re方向题解
1328561843587530 发表于 四川 CTF 440浏览 · 2024-09-13 07:37

pic

有点不同的RC4.
多线程爆破五位字符。

#include <stdio.h>
#include <string.h>
#include <pthread.h>

#define THREADNUM 8
#define CHAR_RANGE (127 - 32 + 1) / THREADNUM

unsigned char png_head[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};

void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len)
{
    int i = 0, j = 0;
    char k[256] = {0};
    unsigned char tmp = 0;
    for (i = 0; i < 256; i++)
    {
        s[i] = i;
        k[i] = key[i % Len];
    }
    for (i = 0; i < 256; i++)
    {
        j = (j + s[i] + k[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
}

void rc4_crypt(unsigned char *s, unsigned char *Data, unsigned long Len)
{
    int i = 0, j = 0, t = 0;
    unsigned long k = 0;
    unsigned char tmp;
    for (k = 0; k < Len; k++)
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
        t = (s[i] + s[j]) % 256;
        Data[k] ^= s[t] ^ 0x11;
    }
}

void *brute_force(void *arg)
{
    int start = *(int *)arg;
    start = start * CHAR_RANGE + 32;
    int end = start + CHAR_RANGE;
    printf("Thread %d: %d-%d\n", *(int *)arg, start, end);
    unsigned char key[5];
    for (int k1 = start; k1 < end; k1++)
    {
        key[0] = k1;
        printf("Thread %d: %d\n", *(int *)arg, key[0]);
        for (int k2 = 32; k2 < 127; k2++)
        {
            key[1] = k2;
            for (int k3 = 32; k3 < 127; k3++)
            {
                key[2] = k3;
                for (int k4 = 32; k4 < 127; k4++)
                {
                    key[3] = k4;
                    for (int k5 = 32; k5 < 127; k5++)
                    {
                        key[4] = k5;
                        unsigned char s[256] = {0};
                        unsigned char pData[8] = {0x85, 0x43, 0x72, 0x78, 0x26, 0xC0, 0x2E, 0x6E};
                        for (int i = 0; i < 8; i++)
                            pData[i] ^= key[1];
                        rc4_init(s, key, 5);
                        rc4_crypt(s, pData, 8);
                        if (memcmp(pData, png_head, 8) == 0)
                        {
                            printf("Key found: %02X %02X %02X %02X %02X\n", key[0], key[1], key[2], key[3], key[4]);
                            printf("Key found: %02X%02X%02X%02X%02X\n", key[0], key[1], key[2], key[3], key[4]);
                            printf("Key found: %c%c%c%c%c\n", key[0], key[1], key[2], key[3], key[4]);
                            pthread_exit(NULL);
                        }
                    }
                }
            }
        }
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t threads[THREADNUM];
    int status;
    int thread_id[THREADNUM];

    for (int i = 0; i < THREADNUM; i++)
    {
        thread_id[i] = i;
        if (pthread_create(&threads[i], NULL, brute_force, (void *)&thread_id[i]) != 0)
        {
            perror("Failed to create thread");
            return 1;
        }
    }

    for (int i = 0; i < CHAR_RANGE; i++)
    {
        if (pthread_join(threads[i], (void **)&status) != 0)
        {
            perror("Failed to join thread");
            return 1;
        }
    }

    return 0;
}
// 0173d

sedRust_happyVm

恐怖rust
前面的东西没太看懂在干嘛。
中间有一段类似base64编码的过程,存储对照表替换的过程前的中间数据。

do
{
    v119 = v113 - 2;
    if ( v113 - 2 >= v111 )
    {
        v204 = &off_443350;
        goto LABEL_261;
    }
    v119 = v113 - 1;
    if ( v113 - 1 >= v111 )
    {
        v204 = &off_443368;
        goto LABEL_261;
    }
    if ( v113 >= v111 )
    {
        v119 = v113;
        v204 = &off_443380;
        LABEL_261:
        sub_403550(v119, v111, v204);
    }
    char1 = *(v109 + v113 - 2);
    char2 = *(v109 + v113 - 1);
    char3 = *(v109 + v113);
    if ( v116 == v115 )
    {
        (sub_40A440)(lpMem, v112, v114);
        v116 = lpMem[3];
        v115 = lpMem[0];
        v112 = lpMem[1];
        v114 = lpMem[2];
    }
    v123 = &v114[v116];
    v124 = 0i64;
    if ( v123 >= v115 )
        v124 = v115;
    v125 = v123 - v124;
    *(v112 + v125) = char1 >> 2;
    v126 = (v116 + 1);
    lpMem[3] = v126;
    v115 = lpMem[0];
    if ( v126 == lpMem[0] )
    {
        (sub_40A440)(lpMem, v112, v125);
        v115 = lpMem[0];
        v126 = lpMem[3];
    }
    v127 = ((char2 >> 4) | (16 * char1)) & 0x3F;
    v112 = lpMem[1];
    v114 = lpMem[2];
    v128 = 0i64;
    if ( lpMem[2] + v126 >= v115 )
        v128 = v115;
    *(lpMem[1] + lpMem[2] + v126 - v128) = v127;
    v129 = v126 + 1;
    lpMem[3] = v129;
    if ( v129 == v115 )
    {
        (sub_40A440)(lpMem, v112, v114);
        v129 = lpMem[3];
        v115 = lpMem[0];
        v112 = lpMem[1];
        v114 = lpMem[2];
    }
    v130 = ((char3 >> 6) | (4 * char2)) & 0x3F;
    v131 = 0i64;
    if ( &v114[v129] >= v115 )
        v131 = v115;
    *(v112 + &v114[v129] - v131) = v130;
    v132 = v129 + 1;
    lpMem[3] = v132;
    if ( v132 == v115 )
    {
        (sub_40A440)(lpMem, v112, v114);
        v132 = lpMem[3];
        v115 = lpMem[0];
        v112 = lpMem[1];
        v114 = lpMem[2];
    }
    v117 = char3 & 0x3F;
    v118 = 0i64;
    if ( &v114[v132] >= v115 )
        v118 = v115;
    *(v112 + &v114[v132] - v118) = v117;
    v116 = (v132 + 1);
    lpMem[3] = v116;
    v113 += 3i64;
}
while ( v113 != 35 );

然后每次使用两个数进入check函数,这样的函数一共用了22个。

check(Src, (v139 << 8) + (v134[v135 - v137 + 1] << 16) - 0x4EFFFFE8, 0x3000201u);
if ( v116 < 3 )
{
    v205 = &off_443018;
    goto LABEL_300;
}
if ( v116 == 3 )
{
    v205 = &off_443030;
    goto LABEL_300;
}
v140 = 0i64;
v141 = v133;
if ( v135 + 2 < v133 )
    v141 = 0i64;
v142 = v134[v135 - v141 + 2];
if ( v135 + 3 >= v133 )
    v140 = v133;
check(Src, (v134[v135 - v140 + 3] << 8) + v142 - 0x5BF70000, 0x3020100u);
if ( v116 < 6 )
{
    v205 = &off_443048;
    goto LABEL_300;
}
v143 = 0i64;
v144 = v133;
if ( v135 + 5 < v133 )
    v144 = 0i64;
v145 = v134[v135 - v144 + 5];
if ( v135 + 4 >= v133 )
    v143 = v133;

最后在这里检测该数据是否为0,为0则flag正确。

在该数据位置下个断点,发现只有这里对其进行了更改:

且每次check函数,如果输入的两个数据是错的,就会加加两次。
直接爆破了。

import frida
import subprocess
from tqdm import tqdm
number = 0
new_number = 0

def on_message(message, data):
    global new_number
    if message['type'] == 'send':
        new_number = message['payload']
    elif message['type'] == "error":
        print(message["description"])
        print(message["stack"])
        print(message["fileName"], "line:", message["lineNumber"], "colum:", message["columnNumber"])
    else:
        print(message)


jscode = open("hook.js", "rb").read().decode()

def check(flag):
    process = subprocess.Popen(
        "80F96BE110F9736464C5328CA22409E1570993AEFAB84BB3F326DF8B2A631027.exe",
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True
    )
    session = frida.attach("80F96BE110F9736464C5328CA22409E1570993AEFAB84BB3F326DF8B2A631027.exe")
    script = session.create_script(jscode)
    script.on('message', on_message)
    script.load()
    process.stdin.write(flag)
    output, error = process.communicate()

if __name__ == "__main__":
    flag = "DASCTF{c669733af3ce4459b88016420b81cb**}"
    check(flag)
    print(f"try {flag} -> {new_number}")
    number = new_number

    for start in range(31, 37, 3):
        print(f"start: {start}, flag: {flag}, number: {number}")
        for i in range(64):
            if new_number <= number - 4:
                number = number - 4 
                break   
            for j in range(64):
                if new_number <= number - 4:
                    break
                k1 = i << 2 | j >> 4
                k2 = (j & 0xf) << 4
                if (32 <= k1 <= 126) and (32 <= k2 <= 126):
                    flag1 = flag[:start] + chr(k1) + chr(k2) + flag[start+2:]
                    check(flag1)
                    if new_number <= number - 2:
                        number1 = number - 2
                        print(f"first flag: {flag1} -> {new_number}")
                        for x in range(64):
                            if new_number <= number1 - 2:
                                break
                            for y in range(64):
                                k2 = (j & 0xf) << 4 | x >> 2
                                k3 = (x & 0x3) << 6 | y
                                if (32 <= k2 <= 126) and (32 <= k3 <= 126):
                                    flag2 = flag[:start] + chr(k1) + chr(k2) + chr(k3) + flag[start+3:]
                                    check(flag2)
                                    if new_number <= number1 - 2:
                                        print(f"\tsecond flag: {flag2} -> {new_number}")
                                        flag = flag2
                                        break
    for i in range(32, 127):
        for j in range(32, 127):
            flag1 = flag[:37] + chr(i) + chr(j) + flag[39:]
            check(flag1)
            if new_number <= number - 3:
                print(f"final flag: {flag1} -> {new_number}")

你这主函数保真么

MLM秒了

void __cdecl __static_initialization_and_destruction_0(int __initialize_p, int __priority)
{
    std::ios_base::Init *v2; // [esp+0h] [ebp-18h]
    std::vector<double> *const v3; // [esp+0h] [ebp-18h]
    Test *const v4; // [esp+0h] [ebp-18h]
    Test2 *const v5; // [esp+0h] [ebp-18h]

    if ( __initialize_p == 1 && __priority == 0xFFFF )
    {
        std::ios_base::Init::Init(v2);
        atexit(__tcf_0);
        std::vector<double>::vector(v3);
        atexit(__tcf_1);
        Test::Test(v4);
        atexit(__tcf_2);
        Test2::Test2(v5);
        atexit(__tcf_3);
    }
}
vector<double> encrypt(const vector<int> &input) {
    int size = input.size();
    vector<double> output(size, 0.0);
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            output[i] += input[j] * cos((i * PI * (j + 0.5)) / size);
        }
        if (i == 0)
            output[i] *= sqrt(1.0 / size);
        else
            output[i] *= sqrt(2.0 / size);
    }
    return output;
}
void Test2::~Test2() {
    std::vector<int> input(strlen(flag));
    for (int i = 0; i < strlen(flag); i++) input[i] = flag[i];
    encrypted = encrypt(input);
    int cd = 0;
    for (auto val : encrypted) in[cd++] = val;
}

void Test::Test() {
    printf("Please input your flag~\n");
    scanf("%s", flag);
    len = strlen(flag);
    if (len != 33) {
        printf("Len error!\n");
        exit(0);
    }
}
void __cdecl Test::~Test(Test *const this)
{
    int i; // [esp+2Ch] [ebp-Ch]

    for ( i = 0; i <= 32; ++i )
    {
        if ( std::abs(check[i] - in[i]) > (long double)(double)0.0001 )
        {
            puts("Wrong!!");
            exit(0);
        }
    }
    puts("Right!!");
}
void __cdecl rot13_encrypt(char *input)
{
    char v1; // al

    while ( *input )
    {
        if ( *input > 64 && *input <= 'Z' || *input > 96 && *input <= 'z' )
        {
            if ( *input <= 64 || *input > 90 )
                v1 = 97;
            else
                v1 = 65;
            *input = (*input - v1 + 13) % 26 + v1;
        }
        ++input;
    }
}

没有AI我真看不出是DCT。
AI直接逆出算法。

#include <iostream>
#include <math.h>

#define PI 3.141592653589793
#define N 33

void rot13encrypt(char* str, int len) {
    for (int i = 0; i < len; i++) {
        if (str[i] >= 'a' && str[i] <= 'z') {
            str[i] = (str[i] - 'a' + 13) % 26 + 'a';
        } else if (str[i] >= 'A' && str[i] <= 'Z') {
            str[i] = (str[i] - 'A' + 13) % 26 + 'A';
        }
    }
}

void enc2(char flag[33], double output[33]) {
    int input[33];
    for (int i = 0; i < 33; i++)
        input[i] = flag[i];
    for (int i = 0; i < 33; i++) {
        printf("output[%d] = %ld ", i, output[i]);
        for (int j = 0; j < 33; j++) {
            output[i] += input[j] * cos((i * PI * (j + 0.5)) / 33);
            // printf(" -> %lf ", output[i]);
        }
        if (i == 0)
            output[i] *= sqrt(33.0);
        else
            output[i] *= sqrt(33.0 / 2.0);
        // printf(" -*-> %lf\n", output[i]);
    }
}

void dec2(double input[N], char flag[N]) {
    double output[N];
    for (int j = 0; j < N; j++) {
        output[j] = 0;
        for (int i = 0; i < N; i++) {
            double coefficient = cos((i * PI * (j + 0.5)) / N);
            if (i == 0)
                coefficient *= sqrt(1.0 / N);
            else
                coefficient *= sqrt(2.0 / N);
            output[j] += input[i] * coefficient;
        }
        // printf("output[%d] = %lf\n", j, output[j]);
        flag[j] = round(output[j]);
    }
}
int main() {
    double result[33];
    unsigned char _check[288] = {
        0xA4, 0x70, 0x3D, 0x0A, 0xD7, 0x0A, 0x80, 0x40, 0xF5, 0x4A, 0x59, 0x86, 0x38, 0xE6, 0x42, 0xC0, 
        0xD8, 0x81, 0x73, 0x46, 0x94, 0x76, 0x21, 0x40, 0x54, 0x74, 0x24, 0x97, 0xFF, 0x90, 0x25, 0xC0, 
        0xA3, 0x23, 0xB9, 0xFC, 0x87, 0xF4, 0xF4, 0xBF, 0xC0, 0x5B, 0x20, 0x41, 0xF1, 0x93, 0x34, 0xC0, 
        0x19, 0xCA, 0x89, 0x76, 0x15, 0xF2, 0x1B, 0x40, 0x3F, 0xC6, 0xDC, 0xB5, 0x84, 0x4C, 0x3D, 0xC0, 
        0x18, 0x95, 0xD4, 0x09, 0x68, 0xE2, 0x2F, 0x40, 0xB5, 0x15, 0xFB, 0xCB, 0xEE, 0x69, 0x35, 0x40, 
        0xB6, 0x84, 0x7C, 0xD0, 0xB3, 0x79, 0x3D, 0x40, 0xEA, 0x21, 0x1A, 0xDD, 0x41, 0x2C, 0x06, 0xC0, 
        0x7C, 0x0A, 0x80, 0xF1, 0x0C, 0x5A, 0x1A, 0xC0, 0xBF, 0x2B, 0x82, 0xFF, 0xAD, 0xE4, 0x10, 0xC0, 
        0x69, 0x35, 0x24, 0xEE, 0xB1, 0xD4, 0x1C, 0xC0, 0x41, 0x65, 0xFC, 0xFB, 0x8C, 0xAB, 0x21, 0x40, 
        0xD8, 0x64, 0x8D, 0x7A, 0x88, 0x86, 0x11, 0xC0, 0x16, 0xFB, 0xCB, 0xEE, 0xC9, 0x63, 0x33, 0xC0, 
        0x0E, 0x4F, 0xAF, 0x94, 0x65, 0x58, 0x32, 0x40, 0x48, 0x1B, 0x47, 0xAC, 0xC5, 0x87, 0x1B, 0x40, 
        0x64, 0xCC, 0x5D, 0x4B, 0xC8, 0x87, 0x2D, 0xC0, 0xD5, 0x09, 0x68, 0x22, 0x6C, 0x38, 0x2D, 0x40, 
        0x20, 0x41, 0xF1, 0x63, 0xCC, 0xBD, 0x38, 0x40, 0x74, 0x24, 0x97, 0xFF, 0x90, 0x3E, 0x27, 0xC0, 
        0x6D, 0xA8, 0x18, 0xE7, 0x6F, 0x82, 0x23, 0xC0, 0xCE, 0x19, 0x51, 0xDA, 0x1B, 0x7C, 0x28, 0x40, 
        0x3C, 0x4E, 0xD1, 0x91, 0x5C, 0xDE, 0x2A, 0x40, 0x90, 0x31, 0x77, 0x2D, 0x21, 0x77, 0x41, 0xC0, 
        0xAE, 0x47, 0xE1, 0x7A, 0x14, 0xDE, 0x41, 0xC0, 0x68, 0xB3, 0xEA, 0x73, 0xB5, 0x15, 0x34, 0xC0, 
        0xD5, 0x78, 0xE9, 0x26, 0x31, 0xD8, 0x43, 0x40, 0x1B, 0x2F, 0xDD, 0x24, 0x06, 0xE1, 0x35, 0x40, 
        0xF8, 0xC2, 0x64, 0xAA, 0x60, 0xD4, 0x3A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    for (int i = 0; i < 33 * 8; i++)
        *((char*)result + i) = _check[i];
    char flag[33] = {0};
    dec2(result, flag);
    for (int i = 0; i < 33; i++)
        printf("%c", flag[i]);
    printf("\n");
    rot13encrypt(flag, 33);
    printf("%s\n", flag);
    return 0;
}

docCrack

在线Word(.docm,.dotm) vba代码提取工具 - 在线工具 (bugscaner.com)获取宏代码
删去一些不必要的代码:

Attribute VB_Name = "ThisDocument"
Attribute VB_Base = "1Normal.ThisDocument"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = True
Attribute VB_Customizable = True

Sub AutoOpen()
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set objShell = CreateObject("WScript.Shell")

    isContinue = 7
    temp = MsgBox("I?am???Vcke?!!!_I???m??Hac?er??!!???_am_Hac?er!!!_I_a?_????ok?r!!!", vbCritical, "Hacked_by_??????")
    Do
        inflag = InputBox("Give me your flag", "Hacked_by_??????")
        If inflag = "" Then
            inflag = "noflag"
        End If
        Result = ""
        For i = 1 To Len(inflag)
            res = Chr(Asc(Mid(inflag, i, 1)) Xor 7)

            Result = Result & res
        Next i

        xpkdb = ...

        tempPath = ThisDocument.Path & "\temp1"
        Set tempfile = fso.CreateTextFile(tempPath, True)
        fso.GetFile(tempPath).Attributes = 2
        tempfile.WriteLine xpkdb
        tempfile.Close

        batPath = ThisDocument.Path & "\temp.bat"
        Set batFile = fso.CreateTextFile(batPath, True)
        fso.GetFile(batPath).Attributes = 2
        batFile.WriteLine "@echo off"
        batFile.WriteLine "cd /d " & ThisDocument.Path
        batFile.WriteLine "certutil -decode temp1 temp|certutil -decode temp temp.exe"
        batFile.WriteLine "del temp"
        batFile.WriteLine "temp.exe " & """" & Result & """"
        batFile.WriteLine "del temp.exe"
        batFile.Close
        Set objExec = objShell.Exec(batPath)
        Set objStdOut = objExec.StdOut
        Do While Not objStdOut.AtEndOfStream
            output = Trim(objStdOut.ReadLine)
        Loop
        output = Left(output, Len(output))
        StartTime = Timer
        Do While Timer < StartTime + 1
            DoEvents
        Loop
        fso.DeleteFile batPath
        fso.DeleteFile tempPath

        If output = "good" Then
            temp = MsgBox("good!!!", , "congratulations!!!")
            Exit Do
        Else
            temp = MsgBox("Sorry, U are wrong!!!", , "Hacked_by_??????")
            isContinue = MsgBox("Continue?", vbYesNo + vbQuestion, "Warning")
        End If
    Loop While isContinue = 6
End Sub

然后两次base64解码数据获取exe文件:

if ( argc == 2 )
{
    for ( j = 0; j < (int)j_strlen(argv[1]) && (unsigned __int64)j < 0x36; ++j )
        result[j + 64] = argv[1][j] << 6;
    for ( j = 0; (unsigned __int64)j < 0x36; ++j )
    {
        if ( result[j] != result[j + 64] )
        {
            sub_140011190("bad");
            return 0;
        }
    }
    sub_140011190("good");
    return 0;
}
else
{
    sub_140011190("no way!!!");
    return 1;
}

直接写脚本:

result = [0] * 54
result[0] = 4288;
result[1] = 4480;
result[2] = 5376;
result[3] = 4352;
result[4] = 5312;
result[5] = 4160;
result[6] = 7936;
result[7] = 5184;
result[8] = 6464;
result[9] = 6528;
result[10] = 5632;
result[11] = 3456;
result[12] = 7424;
result[13] = 5632;
result[14] = 6336;
result[15] = 6528;
result[16] = 6720;
result[17] = 6144;
result[18] = 6272;
result[19] = 7488;
result[20] = 6656;
result[21] = 7296;
result[22] = 7424;
result[23] = 2432;
result[24] = 2432;
result[25] = 2432;
result[26] = 5632;
result[27] = 4416;
result[28] = 3456;
result[29] = 7168;
result[30] = 6528;
result[31] = 7488;
result[32] = 6272;
result[33] = 5632;
result[34] = 3520;
result[35] = 6208;
result[36] = 5632;
result[37] = 4736;
result[38] = 6528;
result[39] = 6400;
result[40] = 7488;
result[41] = 3520;
result[42] = 5632;
result[43] = 5184;
result[44] = 3456;
result[45] = 7488;
result[46] = 7296;
result[47] = 3200;
result[48] = 6272;
result[49] = 7424;
result[50] = 2432;
result[51] = 2432;
result[52] = 2432;
result[53] = 7808;
flag = [0] * 54
for i in range(54):
    flag[i] = (result[i] >> 6) ^ 7
print(flag)
print(''.join([chr(i) for i in flag]))
0 条评论
某人
表情
可输入 255