## 2023 KCTF 年度赛 - CrackMe.exe - Can you crack me?
本程序使用《九连环》的原理, 并在这个基础上将《九连环》的状态分散到十个变量中保存。
* 团队名称:We
* 参赛题目:Can you crack me?
* 题目答案:
```
// 使用 JS 计算注册码
var odd=0;
var code=[];
var e=[1,0,1,0,1,0,0,0,1];
var d=function(i){i%=0x1f;return (0xFFFEC610>>>i)%0xA;}
var f=function(){for(var i=0;i<9;i++)if(e[i])return +i+1;return -1;}
var k,m;
for(var i=0;i<500;i++){
if((odd+i)&1)k=0;
else k=f();
if(k>=0) e[k]=(e[k]+1)&1;
m=(k+12-d(i))%0xA;
console.log(m,i,e);
code.push(m);
if(f()<0)break;
}
code.join('');
// 本题答案
// 582606981190746395118531851185249089744027265368693769576937697816165851808443150195011501950410798490871663488927792799277958360668112074539521851185318514909974002766535869476937695769681626582180144305010501950115040079949037162348792789277927995826067811907483951185218511853490897410272653986937694769376988161658318084433501950105019504207984904716634829277927892779584606681100745395418511852185149009740027365358697769376947696816365821809443050125019501050400790490371673487927
```
* 程序类型:控制台
* 运行截图:(20230826更新了注册码输入方式及修正多解问题)
* 运行程序输入注册码,成功则显示 OK,失败显示 FAIL
* 程序注册码由数字 0-9 组成
#### 设计说明
借鉴九连环的原理,建立九个状态位置;将这九个状态位置分散到 10 个 short 变量中;当需要查看状态时,将 10 个状态变量相互叠加进行异或操作即可得到当前状态。
每读取一个字符,计算出一个介于 0-9 之间的值,0-8 分别代表将第一到第九个状态位置取反(即1变为0,0变为1);其中,第一位取反没有限制,第二至第九位取反时必须保证有且仅有一个为 1 状态且 1 必须位于最近的一个位置(如取第三位的反,就要保证第一位为0, 第二位为1);否则判定失败。
依照上面的规则使所有位置的状态都为 0,则成功。
#### 解题说明
本题关键在于发现这是一个九连环,并找到保存状态的位置。
#### Debug 模式编译
在此模式下进行编译后,运行可以显示每个状态的变化情况。
* Debug 运行图示
* Debug 版本的 inspect 函数可以显示各个分状态与对应的九连环状态。
* 避免直接进行取反操作,而是使用两个16位数分别对10个分状态进行异或操作,增加难度。
#### 其它方法
也可以将本程序改造成一个 DLL, 构造出函数接口,监控触发失败的条件;开始穷举。
## ===== 2023KCTF年度赛-CrackMe-20230919修复多解BUG =====
BUG原因: 局部变量p,左移后未类型转换导致IF多次成立,应为首次成立
修复方法: signed char* 改为 char*,左移后进行类型转换即可
以下修复代码为源文件 CrackMe1.c 第87行至99行
/**
* pos = [0,1,2,...,9]
*/
void step(S32* L, S32* S, int pos){
// S8* p; // signed char* 修复为 char*,修复如下
char* p;
int i;
for(i=0;i<LOCKS32;i++)
L[i]^=S[pos];
if(pos>8){
// p=((S8*)(S+9))+1; // signed char* 修复为 char*,修复如下
p=((char*)(S+9))+1;
// if(((*p)<<3)>=0) *p=(~*p)&0x7F;
// BUG: signed char 左移后未类型转换导致IF多次成立,应为首次成立,修复如下
if((S8)((*p)<<3)>=0) *p=(~*p)&0x7F;
}
}
修复后的压缩包已上传附件 2023KCTF年度赛-CrackMe-20230919修复多解BUG.zip
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
最后于 2023-9-20 21:27
被何松林编辑
,原因: 20230919修复多解BUG