一个娱乐向CM
本帖最后由 zzhwaxy 于 2020-5-15 10:43 编辑## 娱乐向CM
闲着无聊,写了一个CM。
是用VC++6.0编译的win32控制台程序。
## 题目本身并没有难度
感兴趣的可以来挑战一下。
如果做出来了可以分享一下你的答案。
GOOD LUCK!
---
分割线
---
## 下面介绍一下我的设计思路和开放源代码
平时做逆向题目的时候,总会碰到各种循环,所以我就利用跳转难以读懂的特性,稍微动了点手脚。
### 程序的流程
以输入的字符串长度作为switch分支语句的入口点。
难点在于字符串长度不知道,难以预测一开始走的是哪一个。
对每一位输入做判断,每一个判断有两个跳转。
这里使用了 count 来验证最后的跳转。
考虑不周,存在多解的情况。
### 源代码
```c
#include<stdio.h>
#include<string.h>
int main()
{
int len;
int i=0,count=0;
char name;
printf("Please input key:\n");
scanf("%s",name);
len=strlen(name);
if(len<0 || len > 10 )
{
goto end;
}
switch(len){
case 0:
Label0:
if(name=='z')
{
i++;
count-=1;
goto Label1;
}else if(name=='q')
{
i++;
count+=1;
goto Label2;
}
case 1:
Label2:
if(name=='w')
{
i++;
count+=2;
goto Label3;
}else if(name=='r')
{
i++;
count+=1;
goto Label4;
}
case 2:
Label4:
if(name=='x')
{
i++;
count+=1;
goto Label5;
}else if(name=='e')
{
i++;
count+=4;
goto Label6;
}
case 3:
Label6:
if(name=='!')
{
i++;
count+=1;
goto Label7;
}else if(name=='+')
{
i++;
count+=1;
goto Label0;
}
case 4:
Label8:
if(count==9)
{
printf("Success!");
getchar();
getchar();
return 0;
}
else
{
getchar();
getchar();
printf("Failed");
break;
}
case 5:
Label7:
if(name=='<')
{
i++;
count-=1;
goto Label8;
}else if(name=='+')
{
i++;
count+=1;
goto Label2;
}
case 6:
Label5:
if(name=='y')
{
i++;
count+=1;
goto Label6;
}else if(name=='p')
{
i++;
count+=1;
goto Label7;
}
case 7:
Label3:
if(name=='a')
{
i++;
count+=3;
goto Label4;
}else if(name=='x')
{
i++;
count+=2;
goto Label5;
}
case 8:
Label1:
if(name=='h')
{
i++;
count+=2;
goto Label2;
}else if(name=='r')
{
i++;
count+=1;
goto Label3;
}
case 9:
if(name=='z')
{
i++;
count+=1;
goto Label0;
}
else if(name=='/')
{
i++;
goto Label1;
count-=1;
}
break;
}
end:
printf("Failed");
getchar();
getchar();
return 0;
}
``` 本帖最后由 玖公子 于 2020-5-15 10:08 编辑
赤座灯里 发表于 2020-5-14 22:52
#include
#include
大佬太强了,我OD跟了半天,没找出正确的流程,用了你的,发现成功了。
flag是9位数:zzhwaxy!<
0040119F|>837D F4 09 cmp ,0x9;判断长度是否等于9
004011A3|. |0F85 A5000000 jnz trick.0040124E
004011A9|. |68 24504200 push trick.00425024 ;Success!
004011AE|. |E8 CD080000 call trick.00401A80
我以为码追出来了,然后发现不对,必须要取9个字符出来......,找不到正确的流程,只能爆破了! 本帖最后由 赤座灯里 于 2020-5-15 02:17 编辑
#include <stdio.h>
#include <string.h>
int main() {
char input;
int ret;
int i;
int len;
i = 0;
ret = 0;
printf("Please input key:\n");
scanf("%s", input);
len = strlen(input);
if (len < 0 || len > 10) {
LABEL_56:
printf("Failed");
return 0;
}
switch (len) {
case 0:
goto LABEL_5;
case 1:
goto LABEL_9;
case 2:
goto LABEL_13;
case 3:
goto LABEL_17;
case 4:
goto LABEL_21;
case 5:
goto LABEL_36;
case 6:
goto LABEL_40;
case 7:
goto LABEL_44;
case 8:
goto LABEL_48;
case 9:
break;
default:
goto LABEL_56;
}
while (input != 'z') {
if (input != '/')
goto LABEL_56;
++i;
while (1) {
LABEL_48:
if (input == 'h') {
++i;
ret += 2;
goto LABEL_9;
}
if (input != 'r')
break;
++i;
++ret;
LABEL_44:
if (input == 'a') {
++i;
ret += 3;
goto LABEL_13;
}
if (input == 'x') {
++i;
ret += 2;
LABEL_40:
while (input != 'y') {
if (input != 'p')
goto LABEL_44;
++i;
++ret;
LABEL_36:
if (input == '<') {
--ret;
goto LABEL_21;
}
if (input == '+') {
++i;
++ret;
goto LABEL_9;
}
}
++i;
++ret;
goto LABEL_17;
}
}
}
++i;
++ret;
while (1) {
LABEL_5:
if (input == 'z') {
++i;
--ret;
goto LABEL_48;
}
if (input == 'q') {
++i;
++ret;
}
LABEL_9:
if (input == 'w') {
++i;
ret += 2;
goto LABEL_44;
}
if (input == 'r') {
++i;
++ret;
}
LABEL_13:
if (input == 'x') {
++i;
++ret;
goto LABEL_40;
}
if (input == 'e') {
++i;
ret += 4;
}
LABEL_17:
if (input == '!') {
++i;
++ret;
goto LABEL_36;
}
if (input != '+')
break;
++i;
++ret;
}
LABEL_21:
if (ret != 9) {
printf("Failed");
goto LABEL_56;
}
printf("Success!");
return 0;
}
zzhwaxy
flag是猜的,不会去除这种控制流混淆。
这种东西写起来确实不难,按正确逻辑走一遍就行,逆起来就头疼了 1.
2.
赤座灯里 发表于 2020-5-14 22:52
#include
#include
离正确答案很接近了,但是还差一点 支持一下,加密了的,一般复制不了 太好了,只需要这个 玖公子 发表于 2020-5-15 10:05
大佬太强了,我OD跟了半天,没找出正确的流程,用了你的,发现成功了。
flag是9位数:zzhwaxy!<
没想到你们这么快就解出来了。
不过,那个9其实是用来验证结果的,只是为了降低难度,刚巧和字符串长度一致。
源代码我已经在上面开放了。 zzhwaxy 发表于 2020-5-15 07:27
离正确答案很接近了,但是还差一点
按长度匹配必然导致多解,除非成功的逻辑和其他有明显差异
页:
[1]
2