一次更像C语言代码审计的数独逆向

这道题呢是在“墨者学院”上看到的,题目是“逆向分析实训-exe(第2题)“,文末有惊喜,本着学习逆向的想法就去做了下这道题,虽然结果变成了C语言代码审计。。。

另外在做这道题的过程中参考了另外一个大佬的文章,在末尾会给出链接。。。

本人只是一只想学习逆向的菜鸟,文章里可能有错误会不准确的地方,如果有发现请告诉我,非常感谢,没钱的那种~~~穷人,就剩这点脾气了

接下来就开始干活了

IDA打开文件,F5一下,进入main:(菜鸟的自我修养,F5)

看到有success,这个应该就是关键了,要输出success需要满足第一个if(图中1)为假,else里嵌套的第一个if(图中2)为真,小白也不会玩,看到success就直接进入了if ( Sudu::check((Sudu *)&v14) )这个语句,双击跟进这个函数:(这里用血的教训证明了,按部就班的从第一个条件看着走不好吗,啊?)

要返回为真,这里的三个函数的返回值均需要为真,好吧,那就一个个的看,我能怎么办呢,我也不想看,第一个check_block,这里需要注意传入的参数为一个指针的int类型:

这段代码需要结合题目是数独来分析(当然,要是你先看的第一个条件就会好理解很多了),看了老久(我会告诉你我是从大佬的文章里知道的吗,菜鸟不要面子的吗),确认他是对给的数独进行分析,如果满足数独对块的要求,就是每个小的3*3块都是1到9不同的数字,返回值为1,就这样看其实很头疼(大佬没说为什么。。。就只好自己看了。。。),给出自己的分析过程,希望有用:

首先注意这三个地方,第一处,将v2里的值全置为1(除了v2[0],后一样,不用0-8而用1-9是因为1-9刚好是数独可以填的数字),中间将v2里的某几个值置为0(暂且这样说吧),然后最后又对v2的所有值进行判断,如果全部置为0了,return 1,而这是我们要的,否则 return 0,也就是,只要  *(_DWORD *)(a1 + 4 * (v3 + 9 * v4))  的值为1

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,以下是C语言代码实现数独游戏的生成和打印: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 9 #define COL 9 // 初始化数独游戏 void init_sudoku(int sudoku[ROW][COL]) { int i, j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { sudoku[i][j] = 0; } } } // 打印数独游戏 void print_sudoku(int sudoku[ROW][COL]) { int i, j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { printf("%d ", sudoku[i][j]); } printf("\n"); } } // 检查行是否合法 int check_row(int sudoku[ROW][COL], int row, int val) { int j; for (j = 0; j < COL; j++) { if (sudoku[row][j] == val) { return 0; } } return 1; } // 检查列是否合法 int check_col(int sudoku[ROW][COL], int col, int val) { int i; for (i = 0; i < ROW; i++) { if (sudoku[i][col] == val) { return 0; } } return 1; } // 检查3x3的宫格是否合法 int check_box(int sudoku[ROW][COL], int row, int col, int val) { int i, j, row_start, col_start; row_start = (row / 3) * 3; col_start = (col / 3) * 3; for (i = row_start; i < row_start + 3; i++) { for (j = col_start; j < col_start + 3; j++) { if (sudoku[i][j] == val) { return 0; } } } return 1; } // 检查当前数字是否可行 int check_valid(int sudoku[ROW][COL], int row, int col, int val) { return check_row(sudoku, row, val) && check_col(sudoku, col, val) && check_box(sudoku, row, col, val); } // 递归填充数独游戏 int fill_sudoku(int sudoku[ROW][COL], int row, int col) { // 边界条件:填充完最后一行 if (row == 8 && col == 9) { return 1; } // 边界条件:填充完一行 if (col == 9) { row++; col = 0; } // 如果当前位置已经填充了数字,则跳过 if (sudoku[row][col] > 0) { return fill_sudoku(sudoku, row, col + 1); } // 枚举当前位置可以填充的数字 int val; for (val = 1; val <= 9; val++) { // 检查当前数字是否可行 if (check_valid(sudoku, row, col, val)) { sudoku[row][col] = val; // 递归填充下一个位置 if (fill_sudoku(sudoku, row, col + 1)) { return 1; } // 回溯 sudoku[row][col] = 0; } } return 0; } // 生成数独游戏 void create_sudoku(int sudoku[ROW][COL]) { // 初始化随机数种子 srand(time(NULL)); // 生成第一行的随机排列 int i, j, k, first_row[9]; for (i = 0; i < 9; i++) { first_row[i] = i + 1; } for (i = 0; i < 9; i++) { j = rand() % 9; k = first_row[i]; first_row[i] = first_row[j]; first_row[j] = k; } // 填充第一行 for (j = 0; j < 9; j++) { sudoku[0][j] = first_row[j]; } // 递归填充数独游戏 fill_sudoku(sudoku, 0, 0); } int main() { int sudoku[ROW][COL]; init_sudoku(sudoku); create_sudoku(sudoku); print_sudoku(sudoku); return 0; } ``` 运行以上代码,即可生成一个随机的数独游戏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值