目录
一.查壳
二.主函数
三.operate函数
四.storage函数及4618和4620指针功能的解释
五.judge函数
六.求解flag
七.其他--ida字符识别问题
一.查壳
64位无壳
二.主函数
1.这里的pointer_4618和4620是两个相邻的八字节内存单元,其中4620是字符串链表表头head
2.puts和scanf可以通过动态调试得知,这里是使用了命名
三.operate函数
1.ida可能会将该函数参数识别为两个,并且会显示红色,后续分析可以发现该num2变量无用,选中函数名,右键 set item type可以删掉第二个形参
2.该函数的基本功能是:
①对主函数输入的整数input循环除以26,每次循环将余数作为偏移值在0x7FF6266F32D8字符表中查找对应字符,并暂时保存到chr1对应的栈空间中
②从保存的字符串中逐个读取字符,并将其和7(0000 0111)异或,再进行storage()函数操作
③最后的judge函数用于判断字符串是否符合条件,符合则输出成功的弹窗,否则输出失败弹窗
四.storage函数及4618和4620指针功能的解释
根据分析可以发现storage函数是先创建链表新的节点(next),再将传入的chr字符保存起来
1.在主函数中,4618和4620初始时指向了一块16字节的空间,并且将该空间的内容置为0
2.调用storage函数后,先申请一块16字节空间,
然后用var变量保存原来的4618指针值,即var指针指向原来的单元,
对原单元解引用,一部分用于保存字符,另一部分保存next指针
4618最终指向链表下一个节点
3.在程序运行期间,4620始终指向main函数中分配的16字节空间,所以是表头
4.每次动态调试可以发现这两个指针所在单元地址也会变化,但是地址后四位不变,所以这两个指针应该是根据基址加偏移求得
五.judge函数
该函数的基本功能是:每次循环处理链表两个节点的字符,判断字符是否对应等于aV4pY59字符表中的字符(可以根据该字符表反推出输入数据) 如果符合则输出成功的消息弹窗
六.求解flag
#include <iostream>
using namespace std;
unsigned char table[27] = ")(*&^%489$!057@#><:2163qwe";
int find(unsigned char ch) //查找字符在table中的位置
{
for (int i = 0; i < 27; i++)
if (table[i] == ch)
return i;
}
int main()
{
unsigned char arr[15] = "/..v4p$$!>Y59-";
int offset[14]; //offset是每次循环除以26后的余数,即偏移值
long long int num = 0;
for (int i = 0; i < 14; i++)
{
num *= 26; //num每次等于最后剩的余数*26
offset[i] = find(arr[i] ^ 7);
num += offset[i]; //num(num/26后的值)+余数=num原始值
}
printf("%lld", num);
return 0;
}
得到数据:2484524302484524302
运行程序并输入可以看到认证成功
七.其他--ida字符识别问题
ida可能识别不出中文字符串,找到字符串所在空间后选中,按住alt+a,选择unicode即可显示中文
不过这里值得一提的是主函数里的"请输入正确数字"用该方法还是无法正确显示,可能是编码问题,所以动态调试观察程序运行也很重要