吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2598|回复: 2
收起左侧

[分享] hook

[复制链接]
15685738470 发表于 2023-5-26 14:56
内容(1)API函数分析:选取特定的API函数,通过逆向工程技术分析其二进制代码结构和执行流程,了解其参数传递方式和返回值处理方法。
(2)HOOK技术实现:介绍HOOK技术的基本原理和实现方法
(3)OD的动态分析、IDA的静态分析工具的使用
(4)基于攻防世界逆向题easy hook的静态分析简单介绍以下hookHOOK是一种截取信息、更改程序执行流向、添加新功能的强大技术。通过在执行真正的目标函数之前执行实现插入的代码,获取程序执行过程的决定权。
二次开发或补丁 信息截获 安全防护 HOOK使用最多的战场,各类安全软件都会在应用层和内核中安装hook、系统回调、过滤驱动等。从而对系统中所有的进/线程、窗口、文件、网络操作等进行检查、过滤和拦截,在x86系统中,流行在KiFastCallEntry中进行HOOK,以达到间接hook所有系统调用的目的,同时在应用层中通常也会有一些安全模块,通过安装一些应用层HOOK来配合操作API HOOKAPI HOOK是一种HOOK技术,它的原理是通过修改目标程序中的API调用来实现对程序的拦截和修改。在Windows操作系统中,每个API都有一个唯一的标识符,称为函数地址或入口地址。通过修改目标程序中API调用的入口地址,可以将程序的流程控制转移到HOOK函数中,从而实现对程序的拦截和修改。
具体来说,API HOOK的实现分为以下几个步骤:
(1)获取目标程序中API的入口地址;
(2)保存原始的API入口地址,以便在HOOK函数中调用;
(3)修改目标程序中API的入口地址,将其指向HOOK函数;
(4)在HOOK函数中实现自定义的功能或修改;
如果需要,可以在HOOK函数中调用原始的API函数。
通过API HOOK技术,可以实现对目标程序中的API进行拦截和修改,比如监控系统调用、实现自定义的功能、加强安全性等。但是,使用API HOOK技术也有一定的风险和副作用,如果使用不当可能会导致系统不稳定或者安全漏洞。因此,在使用API HOOK技术时需要注意安全性和稳定性问题。HOOK 流程HOOK 本函数MessageBoxA的源代码(能运行)

[C++] 纯文本查看 复制代码
#include <stdio.h>
#include<Windows.h>
typedef int (WINAPI* lpMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
BYTE olddata32[5] = { 0 };
void hook();
void Unhook();
//回调函数 当调用hook时,hook执行完成后调用该函数后再进入main函数
int WINAPI MyMessageboxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    Unhook();
    lpMessageBoxA messagebox = (lpMessageBoxA)GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
    int ret = messagebox(0, "inlinehook", "tip3", 0);
    hook();//函数释放前再次HOOK,为了拦截下次调用
    return ret;
}
void hook()
{
    //获取messagebox的基地址
    DWORD messagebox = (DWORD)GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
    BYTE data[5] = { 0xe9, };
    DWORD offset = (DWORD)MyMessageboxA - messagebox - 5; //计算jmp跳转的偏移量
    //保存前五个字节的数据
    memcpy(olddata32, (const void *)messagebox, 5);
    //把偏移量与JMP指令拼接
    memcpy(&data[1], &offset, 4);
    DWORD oldProtect = 0;
    //更改页面属性 将内存改为可读可写可执行
    VirtualProtect((LPVOID)messagebox, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy((void*)messagebox, data, 5);
    //还原属性
    VirtualProtect((LPVOID)messagebox, 5, oldProtect, &oldProtect);
}
void Unhook()
{

    DWORD messagebox = (DWORD)GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
    DWORD oldProtect = 0;
    VirtualProtect((LPVOID)messagebox, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy((void*)messagebox, olddata32, sizeof(olddata32));
    VirtualProtect((LPVOID)messagebox, 5, oldProtect, &oldProtect);

}
void main()
{
    MessageBoxA(0, "hello", "tip1", 0);
    hook();
    MessageBoxA(0, "hello", "tip2", 0);
}


结果分析Hook前

Hook后,我们的弹窗本该是hello的但是hook后,程序流程被我们修改了。
过程分析(1)首先我们先给MessageBoxA API下软件断点
这里我提供三种方法:
方法一: Ctrl + F 快捷键输入MessageBoxA,跳到一个地址,下软件断点

方法二:在Command后面红色标注的命令框里输入:BP MessageBoxA

方法三:利用吾爱破解里面的OD插件给MessageBoxA下断点

(2)下好断点后程序运行后跳到了760D34B0地址

我们可以看到760D34B0就是我们BP MessageBoxA下断点后的地址,我们可以记住这个地址,因为我们HOOK主要修改的就是该地址,下面我们从汇编代码分析该函数流程
760D34B0 > 8BFF mov edi,edi
它只是一个占位符,方便在调试和优化代码时进行修改。
760D34B2 55 push ebp
760D34B3 8BEC mov ebp,esp
通过这两条指令,函数就可以在堆栈中为局部变量分配存储空间,并在函数执行过程中保存和恢复现场。这样做的好处是可以避免局部变量和其他函数之间的冲突,同时也可以提高函数的可读性和可维护性。
760D34B5 6A FF push -0x1
760D34B7 6A 00 push 0x0
通常被用于函数的参数传递,将参数压入堆栈中,以便被调用函数在堆栈中获取。
760D34B9 FF75 14 push dword ptr ss:[ebp+0x14]
760D34BC FF75 10 push dword ptr ss:[ebp+0x10] ;
760D34BF FF75 0C push dword ptr ss:[ebp+0xC] ;
760D34C2 FF75 08 push dword ptr ss:[ebp+0x8]
这四个push是将MessageBoxA的四个参数压入堆栈中去
760D34C5 E8 D6010000 call user32.MessageBoxTimeoutA
该函数是显示MessageBoxA的弹窗函数
(3)执行函数后我们继续运行,执行该函数后OD显示如图所示

00C4295C 6A 00 push 0x0
00C4295E 68 187CC400 push hookmess.00C47C18 ; ASCII "tip2"
00C42963 68 107CC400 push hookmess.00C47C10 ; ASCII "hello"
00C42968 6A 00 push 0x0
这四个push是hook前的函数流程,将该四个push压入堆栈后,在运行到光标的call中跳入到前面的MessageBoxA函数流程
(4)hook后我们F7进入该函数

我们可以看到760D34B0-760D34B7地址的汇编指令被我们修改了
Hook前的执行指令:
760D34B0 > 8BFF mov edi,edi
760D34B2 55 push ebp
760D34B3 8BEC mov ebp,esp
Hook后执行过程的指令被我们修改成了jmp 00C4110E
00C4110E地址就是我们修改MessageBoxA函数的地址
(5)HOOK函数的逆向分析如下:
这个跳转是VC编译器的特性可以不用管

00C41730是HOOK函数的起始地址

这下面的四个push就是将我们修改MessageBoxA也就是MyMessageBoxA的参数压入堆栈,然后通过下面的call调用

最后执行以前的函数流程,将修改后的MessageBoxA函数的弹窗显示出来
攻防世界逆向题Easy Hook分析过程查壳如下图所示,我们可以知道该程序是32位的PE文件
IDA静态分析步骤一,拉进IDA中按下f5得到main函数的反汇编代码

步骤二:分析伪代码,如下图是我整理的伪代码注释,我们分析完毕后可以知道flag的长度为19,sub_401220()函数就是hook函数,hook的是WriteFile函数。加密过程也在该函数里面。

步骤三:我们运行程序输入1234567890123456789,可以在程序运行目录下找到一个文件,我们用文本的形式打开该文件可以得到下面的结果,并不是我们的输入。

步骤四:进入sub_401220()函数分析,这个函数逻辑清晰地找到了库函数 WriteFile 的地址,向 byte_40C9BC 中载入了 JUMP 指令的字节码 E9,计算了 sub_401080 距离 WriteFile 的第五个字节的距离。我们分析先sub_4010D0()函数
image.png
步骤五:进入sub_4010D0()函数分析,我们分析该函数就可以确定是hook了,我们回到 sub_401220()函数,可以知道sub_401080就是整个程序的关键了。
image.png
步骤六:进入sub_401080()函数分析,该函数就是我们HOOK的返回值,通过sub_401080()函数重新定义了一个WriteFile函数,修改了参数里面的值。我们先分析sub_401140()函数有什么用
image.png
步骤七:进入sub_401140()函数分析,在 sub_401000() 函数加密完 lpBuffer 后,sub_401140又把 WriteFile 函数还原,继续写操作。
image.png
步骤八:进入sub_401000()函数分析,该函数就是我们加密的函数,flag由此解密,简单的异或,第一个判断i=18时,flag = a1 ^ 0x13; i 不等于18时,第二个判断,if (i % 2),满足条件flag = (a1 ^ i) + i,不满足条件flag[i+2] = (res ^ i)。至此IDA的分析就完成了,接下来就是写解密脚本了。
image.png
最后写解密脚本,得到flag
image.png 解密脚本

[C++] 纯文本查看 复制代码
#include <stdio.h>
unsigned char res[] = {
    0x61, 0x6A, 0x79, 0x67, 0x6B, 0x46, 0x6D, 0x2E,
    0x7F, 0x5F, 0x7E, 0x2D, 0x53, 0x56, 0x7B, 0x38,
    0x6D, 0x4C, 0x6E, 0x00};
char flag[19];
int main()
{for (int i = 18; i >= 0; i--){
        if (i == 18)
            flag[i] = res[i] ^ 0x13;
        else{
            if (i % 2){
                flag[i] = (res[i] ^ i) + i;
            }else{
                flag[i+2] = (res[i] ^ i);
            } } }
    for (int i = 1; i < 19; i++)
        printf("%c", flag[i]);}


自此分析完毕

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
笙若 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Hmily 发表于 2023-6-2 18:05
@15685738470 请问文章是原创吗?
axaxax 发表于 2024-4-3 15:13
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-22 21:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表