ida工具应用的保姆级教程
动调
ida动调
hello,大家好,今天给大家讲解一下0xgame一个入门逆向的两种做法
首先,我们下载下来之后用ida打开
之后我们需要找到输入点,以及password
shift+F12打开字符串 搜索password
点击x交叉引用,F5反编译,可以看到输入的逻辑
N重命名一下为了好看一点
之后我们x再引用一下,我们发现上面一层是主函数
我们在这里F2打上断点,然后看一下输入点是不是和我们想的一样
F9启动调试,选中这个
之后一直F8,看看哪里卡住,这里F8是单步,并不会进入函数里面
这里我们就看到运行到我们之前定义的那个函数就停住了,所以说那个是输入点
具体的话就是这一行
if ( !fgets(Buffer, 64, Stream_2) )
return 1;我们再输入行之后再打上断点,避免运行之后直接结束
可以看到,这里走入我们的断点的位置了
之后我们根据大体的功能命名一下
这里我们看到加密的区域块,在命名第二个函数的时候
我们在deal1和deal2这里分别打上断点,看看这个密码输入后的这两个函数在实现什么功能
我们点击F9直接进入到我们的断点的位置,之后点击F7进入函数内部
中间的话需要F5和Tab来回切换层级看,这里的话就不展开了,有点多
之后我们这里进入上述的那一串的字符的区域,这里发现ida是给我们识别出来了
我们在识别出来的基础点击P即可
假如说自己主动还原的话,先点击U,然后点击C,最后点击P即可
这里我们就可以看到deal2的具体逻辑了
__int64 __fastcall deal2(__int64 a1)
{
deal1(
lpAddress_,
(char *)sub_7FF719AA25F4 - (char *)lpAddress_,
(__int64)&unk_7FF719AA50E0,
(__int64)&unk_7FF719AA5130);
return ((__int64 (__fastcall *)(__int64))lpAddress_[0])(a1);
}这里下面这一串同样是一个区域加密
我们仍旧是F2打断点到函数的上面,然后F9过去,之后再F7进入
这里可以看到ida帮助我们还原了
这里我们再点击P即可
这里我们就能成功的看到程序的核心校验逻辑了
之后两种做法从这里分开讲
做法一:patch
之后我们一直F8走,看看正确和错误的分支
这里可以看到错误是走的这个分支,正确的那个仍旧走的是内存解密
这里内存解密应该是输出的flag逻辑我们猜测
这里选中rip的寄存器的,之后点击E,写上我们跳转的地址点击确定
之后这里看到成功的输出了我们的flag
做法二:加密
这里的话就是一个算法,这里的话是大端序的转化
后面的那一行加密算法,就是一个异或,循环移位,加减
转化一下顺序就可以了
target = 0x6E4EA9AABAEB2EB4
# __ROL8__(src ^ 0x819173B095485D69, 21) - 0x1E277ACA3E3B2E23) ^ 0xF216C53D78B72357 = target
# target = (ROL64(src ^ A, 21) - D) ^ B;
# src = ROR64(((target ^ B) + D) , 21) ^ A;
def ROR64(x, n):
return (x >> n) | (x << (64 - n)) & 0xFFFFFFFFFFFFFFFF
src = ROR64(((target ^ 0xF216C53D78B72357)+ 0x1E277ACA3E3B2E23),21) ^ 0x819173B095485D69
print(src.to_bytes(8, byteorder="big").decode("ascii"))附录
这个题目的出题的话,主要是依据的这个函数VirtualProtect,这个和解锁编辑权限之后crypto修改,后面再利用VirtualProtect这个函数回复权限
BOOL __fastcall deal1(void *lpAddress_1, SIZE_T dwSize_1, __int64 a3, __int64 a4)
{
HANDLE hProcess; // rax
DWORD flOldProtect; // [rsp+2Ch] [rbp-94h] BYREF
__int64 v7[18]; // [rsp+30h] [rbp-90h] BYREF
VirtualProtect(lpAddress_1, dwSize_1, 0x40u, &flOldProtect);
crypto1((__int64)v7, a3, a4, 0);
crypto2((__int64)v7, (__int64)lpAddress_1, (__int64)lpAddress_1, dwSize_1);
VirtualProtect(lpAddress_1, dwSize_1, flOldProtect, &flOldProtect);
hProcess = GetCurrentProcess();
return FlushInstructionCache(hProcess, lpAddress_1, dwSize_1);
}好了,实现的原理主要是如下啦,感谢大家观看