拿到同学写的程序,扔进IDA开始分析
找到main函数
先是很长的初始化(用了个数组把a-z存起来了?),把[rbp+830h+count] (int count)初始化为0
再是一个puts和printf调用,然后getchar,把得到的字符放入[rbp+830h+c](char c),之后判断是否为 10 也就是 “\n”,不为回车则进入右边
将c放入edx,count放入eax,cdqe使用eax的最高位拓展rax高32位的所有位(可能和使用64位编译器有关),把edx的低位dl放入[rbp+rax+830h+text](char text[count]),后oount + 1,继续getchar并返回判断是否为"\n"
读取完成后进入左边,要求输入E or D,输入E 到(D的那边大同小异)
继续输入Key,Key被保存在[rbp+830h+k](int k),初始化[rbp+830h+i](int i)为0,判断i和count的大小(估计是一个循环,对输入的text数组每个字符进行操作),小于,进入左侧
看上去是判断是大写字母还是小写,如果是大写字母则进入(小写字母也差不多)
前半部分为 - “A” + k,存入ecx
从mov edx 4EC4EC4Fh 开始能看出来是被优化过的除法或取模(用乘上一个倒数来代替除法,除法耗时是乘法的近几十倍)
因为反推编译器是怎么把除法优化成这样的不擅长
所以把这一段汇编直接摘出来运行
__asm{
mov ecx, 这里放测试的数
mov edx, 4EC4EC4Fh
mov eax, ecx
imul edx
sar edx, 3
mov eax, ecx
sar eax, 1Fh
sub edx, eax
mov eax, edx
imul eax, 1Ah
sub ecx, eax
mov eax, ecx
}
对比测试数和最后eax中保存的数进行推测
测试了几个数后发现这一段表示 mod 26
也就是这一段表示将 ( text[ i ] - ‘A’ + k ) % 26 的结果放到 result[ i ]中
之后进入
检查 result[ ] 前三位是否为 ‘BBC’ 是 则进入
a 赋值为了2000 ; b_0赋值为xxxx ;c_0赋值为了xxxx(这里是个人信息)
其中a的地址进入了zzu
显而易见的 a+=19 (a = 2019)
之后调用了itoa函数将数字 a 转换为字符串 aa
调用malloc申请一块 aa + b_0 + c_0 大小的空间
之后将 aa复制进去,b_0 c_0 拼接上
最终得到的flag便是 2019xxxxxxxxx,也可以输入BBC - k来获得