selph
selph
发布于 2022-11-13 / 200 阅读
0
0

逆向每日一题0x03:Windows_Reverse2

逆向每日一练,题目地址:攻防世界 (xctf.org.cn)

  • 题目来源:DDCTF
  • 题目描述:windows逆向,提交的flag形式为flag{XXXX}。
  • 难度:3

解题分析

查壳:ASPack

image

ESP定律即可脱壳,这里就不展开了

动态调试可以直接让程序跑起来,进入输入函数之后,x86dbg里点暂停,即可断在输入之后的位置,直接就到了我们需要逆向的位置上

这里静态分析来分析这道题

check1

首先是第一个check,功能很简单,就是判断输入是否为0-9,A-F这几个字符,并且输入长度是偶数,如果满足,则返回1,往下继续执行,函数内容比较简单就不进入展开分析了

image

check2

再往下是个字符串生成函数

image

里头主要就是一个循环,主要内容如下,每次取2个字节,计算该字符对应的数值,保存起来

image

然后分别将两个值,合并起来保存到缓冲区(就是把字符串形式的十六进制转换成数值类型)

image

转换完成之后,调用函数生成字符串:

image

主要内容是这个大循环,会执行多次,内容是:

  • 先从刚刚生成的十六进制数据缓冲区里取出来3个字节
  • 然后进行一系列位运算,得到4个值
  • 这4个分别作为索引去数组里拿到一个字节的数值
  • 将数值异或’v’之后,就保存起来用于返回

仔细分析一下,不难发现,这一堆位运算实际在做的事情是:把3个字节的数据拆分成4个数值,就是base64编码算法的那种操作,这里是编码过程,编码完成之后的结果保存起来

image

flag&注册机

最后得到刚刚根据类似base64编码的算法生成的字符串,sprintf函数将其拼接起来,然后进行strcmp循环,比对最后的结果是不是DDCTF

image

这意味着,我们输入的值,通过算法之后生成的字符串需要为这个固定值

既然知道算法的结果,和计算过程,那就可以反向生成我们需要的输入

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
unsigned char byteArr[64] = {
    0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31, 0x3E, 0x3F, 0x3C, 0x3D, 0x3A, 0x3B, 0x38, 0x39, 0x26,
    0x27, 0x24, 0x25, 0x22, 0x23, 0x20, 0x21, 0x2E, 0x2F, 0x2C, 0x17, 0x14, 0x15, 0x12, 0x13, 0x10,
    0x11, 0x1E, 0x1F, 0x1C, 0x1D, 0x1A, 0x1B, 0x18, 0x19, 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00,
    0x01, 0x0E, 0x0F, 0x0C, 0x46, 0x47, 0x44, 0x45, 0x42, 0x43, 0x40, 0x41, 0x4E, 0x4F, 0x5D, 0x59
};

int GetIndex(unsigned char c) {
    for (int i = 0; i < sizeof(byteArr); i++)
    {
        if (c == byteArr[i]) return i;
    }
}

// generate "reve"
string GenStr(const char * input) {
    string res = "";
    unsigned char index1 = GetIndex(input[0] ^ 'v');
    unsigned char index2 = GetIndex(input[1] ^ 'v');
    unsigned char index3 = GetIndex(input[2] ^ 'v');
    unsigned char index4 = GetIndex(input[3] ^ 'v');

    unsigned char c1 = (index1 << 2) + (index2 >> 4);
    unsigned char c2 = ((index2 & 0x0F) << 4) + (index3 >> 2);
    unsigned char c3 = ((index3 & 0x3) << 6) + index4;
    char tmp[100] = { 0 };
    sprintf(tmp,"%X%X%X",c1,c2,c3);
    res += tmp;

    return res;
}

int main()
{
    cout << GenStr("reve");
    cout << GenStr("rse+");
}

计算得到flag:ADEBDEAEC7BE


评论