逆向入门(16)程序逆向篇-Cabeca
这个有点不一样,需要填入两个序列号,找到对应字符串位置
跳转至关键代码处,为了方便看,改一下函数标签
这里还有挺多判断的,先从这个函数头下断,跟一下大概的过程,下面这一部分是用来看是否有没有填满。
这一部分则是判断条件
这里和之前都有一些不一样,之前再往上追的时候就可以找到对应的算法了,但是这一块是直接读的内存的值,往上返也很难找到,这里用在游戏逆向时常用的手法,在内存处下断点
这里下的内存的写入断,此时再去界面上输入字符的时候就可以断下来了。
按a
时就断在这里了,是个switch case
语句吧,输入不同的字母时,将对应的值加到内存处,两个序列都是这么算的。这个时候要把内容都复制下来处理一下方便写注册机
[0x42F714] , 0x427; Case 61 of switch 0042CE34
[0x42F718] , 0x79[0x42F714] , 0x6BC; Case 62 of switch 0042CE34
[0x42F718] , 0x6F[0x42F714] , 0x491; Case 63 of switch 0042CE34
[0x42F718] , 0x2E2[0x42F714] , 0x474D; Case 64 of switch 0042CE34
[0x42F718] , 0x2FA[0x42F714] , 0x400; Case 65 of switch 0042CE34
[0x42F718] , 0xE[0x42F714] , 0x6D0; Case 66 of switch 0042CE34
[0x42F718] , 0xD[0x42F714] , 0x67D; Case 67 of switch 0042CE34
[0x42F718] , 0xC[0x42F714] , 0x750; Case 68 of switch 0042CE34
[0x42F718] , 0xB[0x42F714] , 0x43C; Case 69 of switch 0042CE34
[0x42F718] , 0x63[0x42F714] , 0x764; Case 6A of switch 0042CE34
[0x42F718] , 0x378[0x42F714] , 0xC0; Case 6B of switch 0042CE34
[0x42F718] , 0x4D[0x42F714] , 0x277D; Case 6C of switch 0042CE34
[0x42F718] , 0x22B[0x42F714] , 0x81E; Case 6D of switch 0042CE34
[0x42F718] , 0x5A[0x42F714] , 0xE07; Case 6E of switch 0042CE34
[0x42F718] , 0x62[0x42F714] , 0x8E; Case 6F of switch 0042CE34
[0x42F718] , 0x1D2C[0x42F714] , 0x9A670; Case 70 of switch 0042CE34
[0x42F718] , 0x8C7F3[0x42F714] , 0xD57; Case 71 of switch 0042CE34
[0x42F718] , 0x288[0x42F714] , 0x5FEB; Case 72 of switch 0042CE34
[0x42F718] , 0x21A[0x42F714] , 0x8B0; Case 73 of switch 0042CE34
inc dword ptr ds:[0x42F718][0x42F714] , 0x4BB; Case 74 of switch 0042CE34
[0x42F718] , 0x40[0x42F714] , 0x8C2; Case 75 of switch 0042CE34
[0x42F718] , 0x4B[0x42F714] , 0x1CA6; Case 76 of switch 0042CE34
[0x42F718] , 0x4E[0x42F714] , 0x395; Case 78 of switch 0042CE34
[0x42F718] , 0x26[0x42F714] , 0x251E; Case 77 of switch 0042CE34
[0x42F718] , 0x5[0x42F714] , 0x2D13; Case 79 of switch 0042CE34
[0x42F718] , 0x8[0x42F714] , 0x1900; Case 7A of switch 0042CE34
[0x42F718] , 0x1C8[0x42F714] , 0x428; Case 41 of switch 0042CE34
[0x42F718] , 0x1610[0x42F714] , 0xB1630; Case 42 of switch 0042CE34
[0x42F718] , 0x2[0x42F714] , 0xD86; Case 43 of switch 0042CE34
[0x42F718] , 0x270F[0x42F714] , 0x11A4; Case 44 of switch 0042CE34
[0x42F718] , 0x46FF33C[0x42F714] , 0x11F0A; Case 45 of switch 0042CE34
[0x42F718] , 0x8B3C[0x42F714] , 0x3CC2; Case 46 of switch 0042CE34
[0x42F718] , 0x8618[0x42F714] , 0x3E1A8; Case 47 of switch 0042CE34
[0x42F718] , 0x6C81C[0x42F714] , 0x91E4; Case 48 of switch 0042CE34
[0x42F718] , 0x27E945[0x42F714] , 0x6B42; Case 49 of switch 0042CE34
[0x42F718] , 0x2FC7C3[0x42F714] , 0x516A4; Case 4A of switch 0042CE34
[0x42F718] , 0xB8F47C[0x42F714] , 0x4345A; Case 4B of switch 0042CE34
[0x42F718] , 0x115C7[0x42F714] , 0x1BFDD9; Case 4C of switch 0042CE34
[0x42F718] , 0x12B54[0x42F714] , 0x286D; Case 4D of switch 0042CE34
[0x42F718] , 0xB348C[0x42F714] , 0x401; Case 4E of switch 0042CE34
[0x42F718] , 0x357CE174[0x42F714] , 0x674; Case 4F of switch 0042CE34
[0x42F718] , 0x317CD7[0x42F714] , 0x9C; Case 50 of switch 0042CE34
[0x42F718] , 0x7DD834[0x42F714] , 0x156; Case 51 of switch 0042CE34
[0x42F718] , 0x39CD0[0x42F714] , 0x8627; Case 52 of switch 0042CE34
[0x42F718] , 0xBF44A[0x42F714] , 0x748190; Case 53 of switch 0042CE34
[0x42F718] , 0x854686[0x42F714] , 0xA568; Case 54 of switch 0042CE34
[0x42F718] , 0x13220[0x42F714] , 0x15592; Case 55 of switch 0042CE34
[0x42F718] , 0x302E[0x42F714] , 0x1DD9; Case 56 of switch 0042CE34
[0x42F718] , 0x1C43[0x42F714] , 0x266A; Case 58 of switch 0042CE34
[0x42F718] , 0x2BA96C08[0x42F714] , 0x3CC0; Case 57 of switch 0042CE34
[0x42F718] , 0x4EFC8[0x42F714] , 0x8311; Case 59 of switch 0042CE34
[0x42F718] , 0x1C46[0x42F714] , 0xCE1B; Case 5A of switch 0042CE34
[0x42F718] , 0xB1664
这里有个细节要注意下,就是case 73
的时候,有一个inc
其余的都给的固定值,当然也可以直接将这里替换为0x1
。处理完数据以后,最后的注册机如下。
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
#include <string.h>
#include <inttypes.h> // 添加此头文件以支持 uint64_t 的格式说明符// 定义键值对结构
typedef struct {char key; // 字符键uint32_t first; // 对应 0x42F714 的值uint32_t second; // 对应 0x42F718 的值
} CaseEntry;// 字符映射表
const CaseEntry case_map[] = {// 小写字母部分{'a', 0x427, 0x79}, // Case 61{'b', 0x6BC, 0x6F}, // Case 62{'c', 0x491, 0x2E2}, // Case 63{'d', 0x474D, 0x2FA}, // Case 64{'e', 0x400, 0xE}, // Case 65{'f', 0x6D0, 0xD}, // Case 66{'g', 0x67D, 0xC}, // Case 67{'h', 0x750, 0xB}, // Case 68{'i', 0x43C, 0x63}, // Case 69{'j', 0x764, 0x378}, // Case 6A{'k', 0xC0, 0x4D}, // Case 6B{'l', 0x277D, 0x22B}, // Case 6C{'m', 0x81E, 0x5A}, // Case 6D{'n', 0xE07, 0x62}, // Case 6E{'o', 0x8E, 0x1D2C}, // Case 6F{'p', 0x9A670, 0x8C7F3}, // Case 70{'q', 0xD57, 0x288}, // Case 71{'r', 0x5FEB, 0x21A}, // Case 72{'s', 0x8B0, 0x0}, // Case 73 (特殊INC指令){'t', 0x4BB, 0x40}, // Case 74{'u', 0x8C2, 0x4B}, // Case 75{'v', 0x1CA6, 0x4E}, // Case 76{'w', 0x395, 0x26}, // Case 78{'x', 0x251E, 0x5}, // Case 77{'y', 0x2D13, 0x8}, // Case 79{'z', 0x1900, 0x1C8}, // Case 7A// 大写字母部分{'A', 0x428, 0x1610}, // Case 41{'B', 0xB1630, 0x2}, // Case 42{'C', 0xD86, 0x270F}, // Case 43{'D', 0x11A4, 0x46FF33C}, // Case 44{'E', 0x11F0A, 0x8B3C}, // Case 45{'F', 0x3CC2, 0x8618}, // Case 46{'G', 0x3E1A8, 0x6C81C}, // Case 47{'H', 0x91E4, 0x27E945}, // Case 48{'I', 0x6B42, 0x2FC7C3}, // Case 49{'J', 0x516A4, 0xB8F47C}, // Case 4A{'K', 0x4345A, 0x115C7}, // Case 4B{'L', 0x1BFDD9, 0x12B54}, // Case 4C{'M', 0x286D, 0xB348C}, // Case 4D{'N', 0x401, 0x357CE174}, // Case 4E{'O', 0x674, 0x317CD7}, // Case 4F{'P', 0x9C, 0x7DD834}, // Case 50{'Q', 0x156, 0x39CD0}, // Case 51{'R', 0x8627, 0xBF44A}, // Case 52{'S', 0x748190, 0x854686}, // Case 53{'T', 0xA568, 0x13220}, // Case 54{'U', 0x15592, 0x302E}, // Case 55{'V', 0x1DD9, 0x1C43}, // Case 56{'W', 0x266A, 0x2BA96C08}, // Case 58{'X', 0x3CC0, 0x4EFC8}, // Case 57{'Y', 0x8311, 0x1C46}, // Case 59{'Z', 0xCE1B, 0xB1664} // Case 5A
};// 查找函数
const CaseEntry* find_case(char key) {for (size_t i = 0; i < sizeof(case_map) / sizeof(case_map[0]); i++) {if (case_map[i].key == key) {return &case_map[i];}}return NULL; // 未找到
}// 计算字符串的累加和
void calculate_sums(const char* str, uint64_t* sum_first, uint64_t* sum_second) {*sum_first = 0;*sum_second = 0;printf("\n字符串: \"%s\"\n", str);printf("+-------+------------+------------+----------------+----------------+\n");printf("| 字符 | First值 | Second值 | First累加 | Second累加 |\n");printf("+-------+------------+------------+----------------+----------------+\n");for (size_t i = 0; str[i] != '\0'; i++) {const CaseEntry* entry = find_case(str[i]);if (entry) {uint32_t original_second = entry->second;uint32_t actual_second = original_second;// 特殊处理字母's'(小写)if (entry->key == 's') {actual_second += 1; // 执行INC指令}// 更新累加值*sum_first += entry->first;*sum_second += actual_second;// 打印当前字符的处理结果if (entry->key == 's') {printf("| '%c' | %-10u | %-3u (INC+1) | %-14" PRIu64 " | %-14" PRIu64 " |\n",entry->key,entry->first,actual_second,*sum_first,*sum_second);}else {printf("| '%c' | %-10u | %-10u | %-14" PRIu64 " | %-14" PRIu64 " |\n",entry->key,entry->first,actual_second,*sum_first,*sum_second);}}else {printf("| '%c' | 未找到映射 | 跳过处理 | %-14" PRIu64 " | %-14" PRIu64 " |\n",str[i], *sum_first, *sum_second);}}printf("+-------+------------+------------+----------------+----------------+\n");
}int main() {char input[100];printf("\n\n输入任意字符串进行累加计算 (输入exit退出):\n");while (1) {printf("> ");fgets(input, sizeof(input), stdin);// 移除换行符input[strcspn(input, "\n")] = '\0';if (strcmp(input, "exit") == 0) break;uint64_t sum_first, sum_second;calculate_sums(input, &sum_first, &sum_second);printf("\n最终累加和:\n");printf("First 累加和: %" PRIu64 "\n", sum_first);printf("Second累加和: %" PRIu64 "\n", sum_second);printf("-----------------------------------\n");}return 0;
}
搞定