[安洵杯 2019]crackMe
程序异常处理的一题,刚开始还以为是双线程(),因为input和hook的弹窗这两个函数之间没有跳转的关系。
在动调的过程中,没发现是异常处理,就把跳转进异常处理的汇编给nop掉了,有点蠢哈哈哈哈哈
跟踪main()函数无果的情况下,通过跟踪关键字符串,然后通过交叉引用的方法理清函数逻辑也是一种思路。
有资料说可以通过Imports找到引用的库,一下就可以定位到,进去找X
注册向量异常处理程序
AddVectoredExceptionHandler 函数
注册向量异常处理程序
AddVectoredExceptionHandler(0, Handler);---->第一个参数0表示注册的Handler函数在出现异常后会优先触发,第二个参数表示触发执行的函数
SetUnhandledExceptionFilter
使应用程序能够取代进程的每个线程的顶级异常处理程序。
调用此函数后,如果在未调试的进程中发生异常,并且异常会将其设置为未处理的异常筛选器,该筛选器将调用 lpTopLevelExceptionFilter 参数指定的异常筛选器函数。
SetUnhandledExceptionFilter(TopLevelExceptionFilter);--->TopLevelExceptionFilter指向顶级异常筛选器函数的指针,每当 UnhandledExceptionFilter 函数得到控制时,都会调用该函数,并且进程不会被调试。
SM4:
0xA3B1BAC6 是 SM4 的特征值
密钥为传入的 v2 即 "where_are_u_now?"
脚本解密
base64:
'!'--->'='
这里是刚好24位,所以就不用补位
以及表后移了24位,还大小写交换了
[NPUCTF2020]你好sao啊
单走一个6
base64的加密解密:
加密为3位变4位
解密反过来
这里是由4位变三位,不难猜出这个就是解密,那么逆向的话,就要用加密的脚本
或者这样看:
只有加密后的密文才有=号,所以输入进来的是密文,那么这个就是解密
再或者这样看:
左移6位再or上右边的两位,就是解密的过程
字节最高八位
6
6
这里的数据其实是超出8位的,然而按照base64加密的规则【我乱说的】,我们只能取后面高地址的八位【我也不知道是高地址还是低地址】。
也有wp是用脚本转字节的
#include <iostream> #include <cstring> int main() { unsigned long long s[] = { 0xFD370FEB59C9B9E, 0xDEAB7F029C4FD1B2, 0xFACD9D40E7636559, 0x4, 0x0 }; for (int i = 0; i < 25; i++) { int c = (int) * ((unsigned char *) (s) + i); std::cout << "\\x" << std::hex << c; } std::cout << std::endl; return 0; }