[C] 新人第一帖,CM稍微加了点难度
本帖最后由 zunmx 于 2024-5-17 11:07 编辑cm描述
编程语言:C
编译工具:MinGW-CMake
加壳:否
静态编译:是
编译平台:Windows 10 22H2
平台: X64
cm截图
cm单一样例
auth name :zunmxZunMX52pj66
authkey :pVMXNdEeKYpMDNKd
题目要求
1.找到关键点
2.输出 You arewinner
3.输入正确的 name 和 key
4.搓出注册机
信誉和安全
https://s.threatbook.com/report/file/628ee08fa3306fa5fdabf3b7778e62f9d0df1ac93f35fa08bb618c6c700dc14c
下载地址
https://www.123pan.com/s/rSNuVv-YWnmH.html提取码:52pj
推荐工具
· x64dbg
· ida
本帖最后由 爱飞的猫 于 2024-5-17 21:46 编辑
加了一些混淆代码,但是从成功信息部分反推就能剔除“花代码”了。
```c
void __noreturn checker(void)
{
if ( ++g_flag_ZERO == 1 && !g_flag2_ZERO ) // 两个值必须都等于 0
{
gTable2 = getNum(1);
if ( (unsigned int)getNum(3) == 16 && gTable2 == '`' )
{
printf(" You are ");
Num = getNum(5); // 'w'
printf("%c", Num);
v7 = getNum(6); // 'i'
printf("%c", v7);
v8 = getNum(7); // 'n'
printf("%c", v8);
v9 = getNum(7); // 'n'
printf("%c", v9);
printf("er\n");
g_flag_ZERO = 1001;
}
}
```
反推回去:
```c
__int64 __fastcall handler(char *name, char *passwd)
{
i = 0i64;
while ( 1 )
{
// 对用户名进行变形
v5 = name;
if ( (unsigned __int8)(name - 0x61) <= 0xFu )
v6 = gTable1;
else
v6 = gTable1;
v7 = i + v6;
if ( (i & 1) != 0 )
v7 = gTable2;
else
LOBYTE(v7) = gTable1;
v8 = v7 - 0x7C - gTable1;
final_key = v8 - 0x16;
if ( ((v8 - 0x57) & 0xDFu) > 0x19 )
final_key = gTable1; // 有用的代码到这里就结束了
// final_key 为对应位置的序列号字符
printf(&byte_140013044, (unsigned int)final_key);
// ... 省略一部分 ...
if ( passwd != final_key ) // 必须相等,不成立
break;
if ( ++i == 16 ) // 循环结束,开始检测
{
// 省略部分代码
checker();
}
}
}
```
算法注册机:
```cpp
#include <cstdint>
#include <cstring>
#include <iostream>
#include <string>
uint8_t gTable1[] = {0x78, 0x6D, 0x6E, 0x75, 0x6C, 0x4F, 0x6F, 0x30, 0x5A, 0x7A, 0x69, 0x6A, 0x4E, 0x55, 0x58, 0x4D};
uint32_t gTable2[] = {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f};
std::string generate_key(const char *name)
{
std::string result{};
if (strlen(name) != 16)
{
return "err: strlen(name) is not 16";
}
for (int i = 0; i < 16; i++)
{
uint8_t c = name;
if ('a' <= c && c <= 'f') {
c -= 'a' - 1;
} else {
c &= 15;
}
c = gTable1 + i;
c = (i & 1) ? gTable2 : gTable1;
c = c - 0x7C - gTable1;
char s = static_cast<char>(c) - 0x16;
if (((c - 0x57) & 0xDF) > 0x19) {
s = gTable1;
}
result += s;
}
return result;
}
int main()
{
char name = "0123456789abcdef";
auto serial = generate_key(name);
std::cout << serial << std::endl;
return 0;
}
```
用算出来的序列号输入进去:
```text
[#] Crack me for C language. 52pojie--zunmx
Press your auth name :0123456789abcdef
Press your auth key:PdnXnZEUdYoMcMKd
You are winner``` zunmx 发表于 2024-5-20 09:38
大佬分析的很透彻,虚心请教一下,大佬使用反编译工具是什么,是通过IDA的源代码吗?我尝试使用 ...
是的,这是 IDA Pro 反编译到伪代码的功能。
“花代码”(暗桩)是手动分析的。因为在伪代码到处乱翻,偶然发现了最终提示成功的位置,可以发现成功的条件是两个全局变量的值都需要为 0。因此任何对这两个值(默认是 0)进行更改的操作所在的分支都可以忽略不看,只看进入该分支的条件即可。在 IDA 中可以对变量按下 x 键查看引用(读取、写入)操作的地方。
此外代码编译不是发布模式,保留了函数名。如果没有函数名可能需要看(猜)更久一点。 无奈只会爆破,呜呜呜 爱飞的猫 发表于 2024-5-17 21:36
加了一些混淆代码,但是从成功信息部分反推就能剔除“花代码”了。
```c
大佬分析的很透彻{:1_921:},虚心请教一下,大佬使用反编译工具是什么,是通过IDA的源代码吗?我尝试使用源代码和调试,感觉逻辑比较混乱,您是如何分辨出哪些是花代码的?{:1_893:} #include <stdio.h>
#include <string.h>
#include <immintrin.h> // For SSE instructions
__int128 xmmword_1400130E0; // Placeholder for memory content
__int128 xmmword_1400130F0;
__int128 xmmword_140013100;
__int128 xmmword_140013110;
__int128 xmmword_140017070;
__int128 xmmword_140017080;
__int128 xmmword_140017090;
void handler(char* name, char* key);
unsigned int getNum(int index);
int main(int argc, char *argv[], char *envp[]) {
unsigned int num;
unsigned int v4;
unsigned int v5;
char v7;
_main(argc, argv, envp);
// Load constants using SSE instructions
__int128 key = _mm_loadu_si128((__m128i*)&xmmword_1400130E0);
xmmword_140017070 = _mm_loadu_si128((__m128i*)&xmmword_1400130F0);
xmmword_140017080 = _mm_loadu_si128((__m128i*)&xmmword_140013100);
// Clearing the buffer with spaces
memset(v7, ' ', 32);
xmmword_140017090 = _mm_loadu_si128((__m128i*)&xmmword_140013110);
printf("[#] Crack me for C language. 52pojie--zunmx\n");
printf(" Press your auth name :");
scanf("%s", v7);
printf(" Press your auth key:");
scanf("%s", &v7);
// Process user input
handler(v7, &v7);
printf(" You are ");
num = getNum(8);
printf("%c", num);
v4 = getNum(9);
printf("%c", v4);
v5 = getNum(10);
printf("%cer\n", v5); // Fixed missing comma in the format specifier
return 0;
} 本帖最后由 zunmx 于 2024-5-22 09:26 编辑
Weah 发表于 2024-5-22 00:32
无奈只会爆破,呜呜呜
这里我也稍微加了点花代码,但是看样子只是改了字符,但是winner是不是少了个字符呢?{:1_921:}
页:
[1]