吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1459|回复: 9
收起左侧

[ReverseMe] ReverseMe Lv1 无花无壳纯C语言编写

[复制链接]
陨落星辰 发表于 2025-3-27 22:28
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。

编译环境:C语言 ,Vs2022 msvc x86 Release
特点:无花无壳,纯手写控制流平坦化+虚假控制流。因此可能会被杀毒软件特征。
注意是ReverseMe,请各位大佬找出正确的密码(flag),爆破无效。
软件的输入输出如图所示。


查毒链接:https://www.virustotal.com/gui/file/4529398e2e7905188b260d7f148208ef3d9b3b6cd4ff5a61674ed137ccd90624/detection
附件解压密码:123

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 3吾爱币 +3 热心值 +3 收起 理由
zjoep + 1 + 1 热心回复!
st0rm + 1 + 1 用心讨论,共获提升!
chinawolf2000 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

geesehoward 发表于 2025-3-28 16:03
本帖最后由 geesehoward 于 2025-3-28 16:12 编辑


控制台程序,直接拖入IDA,main函数如下
[C] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // edx
  int v4; // ecx
  unsigned int v5; // esi
  unsigned int v6; // edi
  int v7; // ebx
  unsigned __int64 v8; // kr30_8
  unsigned __int64 v9; // rcx
  unsigned int v10; // eax
  __int64 v11; // rax
  unsigned int v12; // eax
  int v13; // edx
  unsigned int v14; // esi
  int v15; // ebx
  unsigned int v16; // edi
  unsigned int v17; // ecx
  unsigned int v18; // eax
  unsigned int v19; // edx
  unsigned __int64 v20; // kr68_8
  unsigned int v21; // kr20_4
  int v22; // ecx
  char v23; // [esp+0h] [ebp-150h]
  char v24; // [esp+10h] [ebp-140h]
  int v25; // [esp+10h] [ebp-140h]
  unsigned int v26; // [esp+14h] [ebp-13Ch]
  int v27; // [esp+18h] [ebp-138h]
  int v28; // [esp+1Ch] [ebp-134h]
  int v29; // [esp+1Ch] [ebp-134h]
  unsigned int v30; // [esp+20h] [ebp-130h]
  unsigned int v31; // [esp+20h] [ebp-130h]
  int v32; // [esp+24h] [ebp-12Ch]
  int v33; // [esp+28h] [ebp-128h]
  char Arglist[260]; // [esp+48h] [ebp-108h] BYREF
 
  while ( 1 )
  {
    memset(Arglist, 0, 0x100u);
    xmmword_4043C8 = xmmword_404060;
    sub_401020(":Please input password(without spaces).\r\n[:] ", v23);
    sub_401060("%s", (char)Arglist);
    v3 = 0;
    v30 = 0;
    do
    {
      v4 = *((char *)&xmmword_4043C8 + v3);
      v5 = 0xDEADC0DE;
      v28 = v4;
      v6 = 0xDEADC0DE;
      v24 = -1;
      LOBYTE(v7) = 0xDE;
      while ( 1 )
      {
        while ( 1 )
        {
          while ( v6 > 0xC7B5A3F1 || v6 >= 0xC7B5A3F1 && v5 > 0x9D4E6F82 )
          {
            if ( v5 == -559038242 && v6 == -559038242 )
            {
              if ( (v7 & 1) != 0 )
              {
                v5 = -1655804030;
                v6 = -944397327;
              }
              else
              {
                v5 = -944397327;
                v6 = -1655804030;
              }
              v11 = 345069055i64 * (unsigned int)(v4 + 197);
              v4 = v28;
              v7 = HIBYTE(HIDWORD(v11));
            }
          }
          if ( v5 != -1655804030 || v6 != -944397327 )
            break;
          v5 = -944397327;
          v6 = -1655804030;
          LOBYTE(v7) = 0;
        }
        if ( v5 == 0xA8C3D7E4 && !v6 )
          break;
        if ( v5 == -944397327 && v6 == -1655804030 )
        {
          v24 = v4 & 0x3A | ~(_BYTE)v4 & 0xC5;
          v8 = 0x9D4E6F82C7B5A3F1ui64 * (int)(v4 & 0xFFFFFF3A | ~(_BYTE)v4 & 0xC5);
          v5 = -1463560220;
          v9 = 3781878765i64 * HIDWORD(v8)
             + ((3781878765u * (unsigned __int64)(-944397327 * (v4 & 0xFFFFFF3A | ~(_BYTE)v4 & 0xC5))) >> 32);
          v10 = (((250939340i64 * (unsigned int)v8 + (unsigned __int64)(unsigned int)v9) >> 32) + HIDWORD(v9)) >> 32;
          HIDWORD(v9) += (250939340i64 * (unsigned int)v8 + (unsigned __int64)(unsigned int)v9) >> 32;
          v4 = v28;
          v7 = (__PAIR64__(v10, HIDWORD(v9))
              + 250939340i64 * HIDWORD(v8)
              + ((v8 - (__PAIR64__(v10, HIDWORD(v9)) + 250939340i64 * HIDWORD(v8))) >> 1)) >> 31;
          v6 = 0;
        }
      }
      *((_BYTE *)&xmmword_4043C8 + v30) = v24 - v30 * (15 - v30);
      v3 = v30 + 1;
      v30 = v3;
    }
    while ( v3 < 0x10 );
    v12 = 0;
    v27 = 0;
    v26 = 0;
    do
    {
      v13 = *((char *)&xmmword_4043C8 + v12);
      v14 = -559038242;
      v15 = Arglist[v12];
      v16 = -559038242;
      v25 = v13;
      v33 = v15;
      LOBYTE(v17) = -34;
      v29 = -1;
      while ( 1 )
      {
        while ( 1 )
        {
          while ( v16 > 0xC7B5A3F1 || v16 >= 0xC7B5A3F1 && v14 > 0x9D4E6F82 )
          {
            if ( v14 == -559038242 && v16 == -559038242 )
            {
              if ( (v17 & 1) != 0 )
              {
                v14 = -1655804030;
                v16 = -944397327;
              }
              else
              {
                v14 = -944397327;
                v16 = -1655804030;
              }
              v21 = v15 + v13;
              v13 = v25;
              v17 = v21 / 0xC725A3A;
            }
          }
          if ( v14 != -1655804030 || v16 != -944397327 )
            break;
          v14 = -944397327;
          v16 = -1655804030;
          LOBYTE(v17) = 0;
        }
        if ( v14 == -1463560220 && !v16 )
          break;
        if ( v14 == -944397327 && v16 == -1655804030 )
        {
          v32 = v15 & ~v13;
          v29 = (v32 | v13 & ~v15) == 0;
          v31 = (0x9D4E6F82C7B5A3F1ui64 * ((v32 | v13 & ~v15) == 0)) >> 32;
          v14 = -1463560220;
          v18 = (((250939340i64 * (unsigned int)(-944397327 * v29)
                 + ((0x4C2B8975A651791Di64 * (unsigned __int64)((v32 | v13 & ~v15) == 0)) >> 32)) >> 32)
               + ((3781878765i64 * v31 + ((3781878765u * (unsigned __int64)(unsigned int)(-944397327 * v29)) >> 32)) >> 32)) >> 32;
          v19 = ((250939340i64 * (unsigned int)(-944397327 * v29)
                + ((0x4C2B8975A651791Di64 * (unsigned __int64)((v32 | v13 & ~v15) == 0)) >> 32)) >> 32)
              + ((3781878765i64 * v31 + ((3781878765u * (unsigned __int64)(unsigned int)(-944397327 * v29)) >> 32)) >> 32);
          v15 = v33;
          v20 = __PAIR64__(v18, v19)
              + 250939340i64 * v31
              + ((__PAIR64__(v31, -944397327 * v29) - (__PAIR64__(v18, v19) + 250939340i64 * v31)) >> 1);
          v13 = v25;
          v17 = v20 >> 31;
          v16 = 0;
        }
      }
      v22 = v27;
      if ( !v29 )
        v22 = -1;
      v12 = v26 + 1;
      v27 = v22;
      v26 = v12;
    }
    while ( v12 < 0xF );
    if ( v22 )
      puts("[x]:Failed.\r\n");
    else
      puts("[o]:Success.\r\n");
  }
}

其中几个while(1)循环都是干扰项,简化代码,得到如下有效代码
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int result = 0;
    char Arglist[260]; // [esp+48h] [ebp-108h] BYREF
 
    while (1)
    {
        result = 0;
        memset(Arglist, 0, 0x100u);
        unsigned char Keybase[] = { 0xF0, 0xFA, 0xBE, 0x52, 0x5C, 0x54, 0x5C, 0x6F, 0xAE, 0xAA, 0x54, 0x99, 0x59, 0xB8, 0x86, 0x00 };
        printf(":Please input password(without spaces).\r\n[:] ");
        scanf_s("%s", Arglist, 260);
        for(int i = 0;i < 0x10;i++)
        {
            char c = Keybase[i];
            char v24 = c & 0x3A | ~(_BYTE)c & 0xC5;
            Keybase[i] = v24 - i * (15 - i);
        }
        for(int i = 0;i < 0xF;i++)
        {
            char v13 = Keybase[i];
            char v15 = Arglist[i];
            char v32 = v15 & ~v13;
            int v29 = (v32 | v13 & ~v15) == 0;
            if (!v29)
                result = -1;
        }
        if (result)
            puts("[x]:Failed.\r\n");
        else
            puts("[o]:Success.\r\n");
    }

分析两段循环,第一段是转化Key,第二段是将输入的flag按位与转化的key做运算,运算结果为0,(key&~flag) |(~key & flag),等同于判断key=flag。
修改代码
Keybase[0xF] = 0;
printf("Key:%s\n", Keybase);


打印得到flag



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
陨落星辰 + 1 + 1 我很赞同!

查看全部评分

怜渠客 发表于 2025-3-27 23:39
补充一个解出的代码,是在ai帮助下写的,我对py不太熟悉

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x
Cl0sueN1ght 发表于 2025-3-28 11:12
本帖最后由 Cl0sueN1ght 于 2025-3-28 11:13 编辑

明码

main 函数反编译观察到疑似的加密字符串(s)和用户输入的(ms)

memset(ms, 0, 0x100u);
s = xmmword_404060;                         // 86B8599954AAAE6F5C545C52BEFAF0h
sub_401020("Please input password(without spaces).\r\n[:] ", v23);
sub_401060("%s", (char)ms);

追踪 s 的数据流,serial 的解密操作

do
{
    sc = *((char *)&s + vc3_);
    sc2 = sc & 0x3A | ~(_BYTE)sc & 0xC5;
    *((_BYTE *)&s + vc3) = sc2 - vc3 * (15 - vc3);
    vc3_ = vc3 + 1;
    vc3 = vc3_;
}
while ( vc3_ < 0x10 );

将解密的 serial 与 m_serial 进行比较


do
{
    sc_1 = *((char *)&s + vc);
    msc = ms[vc];
    m = msc & ~sc_1;
    nz = (m | sc_1 & ~msc) == 0;
    if ( !nz )
        f = -1;
    vc = vc2_ + 1;
}
while ( vc < 0xF );

动态调试

由于程序允许多次验证,输入 "Cl0sueN1ght is coming",观察 base+0x000043C8 (17352d) 内存

004043C8  35 31 61 73 6D 5F 63 72 33 39 5F 30 78 63 35 C5  51asm_cr39_0xc5Å  
004043D8  00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00  ................  

反混淆

混淆控制流呈现明显的模板的特征,提取完数据流后,经过编译优化,得到结果


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x
Suppose 发表于 2025-3-28 19:44
下载>>拖入IDA>>F5>>伪代码扔到deepseek>>得到以下代码。。。
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
int main()
{
    const unsigned char initial_data[16] = {
        0xF0,0xFA,0xBE,0x52,0x5C,0x54,0x5C,0x6F,
        0xAE,0xAA,0x54,0x99,0x59,0xB8,0x86 };
     
    unsigned char processed[16] = { 0 };
 
    // 处理初始数据生成密码
    for (int i = 0; i < 15; ++i) {
        processed[i] = (unsigned char)((initial_data[i] ^ 0xC5) - i * (15 - i));
    }
 
    std::cout << processed;
}
怜渠客 发表于 2025-3-27 23:03

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
陨落星辰 + 1 + 1 66666,走一波。

查看全部评分

qinke513 发表于 2025-3-28 15:15
牛   学习了

免费评分

参与人数 1吾爱币 -8 违规 +1 收起 理由
勇者为王 -8 + 1 CM版块严禁灌水!

查看全部评分

WAPLAY 发表于 2025-3-28 15:53
牛   学习了

免费评分

参与人数 1吾爱币 -8 违规 +1 收起 理由
勇者为王 -8 + 1 CM版块严禁灌水!

查看全部评分

tomhex 发表于 2025-3-29 09:11
菜鸟学习了

免费评分

参与人数 1吾爱币 -15 违规 +1 收起 理由
bian96 -15 + 1 警告:CM区等技术版块禁止回复『与主题无关非技术内容』,违者重罚!

查看全部评分

WXjzc 发表于 2025-3-31 10:21
第一段可以简化成这样,第二段只是比较
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
memset(Arglist, 0, 0x100u);
    keys = xmmword_404060;            // 86B8599954AAAE6F5C545C52BEFAF0
    sub_401020("[*]:Please input password(without spaces).\r\n[:] ");
    scanf("%s", Arglist);
    idx = 0;
    v29 = 0;
    do
    {
      v4 = *((char *)keys[idx]);
      v5 = -559038242;
      v27 = v4;
      v23 = v4 & 0x3A | ~(_BYTE)v4 & 0xC5;
      *((_BYTE *)keys[idx]) = v23 - idx * (15 - idx);
    }
    while ( idx < 0x10 );

python写一个脚本解密
[Python] 纯文本查看 复制代码
1
2
3
4
5
6
7
hex_str='86B8599954AAAE6F5C545C52BEFAF0'
key_bytes = bytes.fromhex(hex_str)[::-1]
for i in range(15):
    b = key_bytes[i]
    val = (b ^ 0xc5) - i * (15 - i)
    print(chr(val),end='')
# 51asm_cr39_0xc5
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-3 23:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表