吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3189|回复: 10
上一主题 下一主题
收起左侧

[调试逆向] Managed API Hook: 逆向分析之花

[复制链接]
跳转到指定楼层
楼主
BeneficialWeb 发表于 2024-6-19 14:59 回帖奖励

API Hook: 逆向分析之花

理论基础

代码逆向分析中,Hook是一种截取信息、更改程序执行流程、添加新功能的技术。

使用DLL 注入技术可以驱使目标进程强制加载用户指定的DLL文件。

.NET Framework 中DLL提供的API称之为Managed API。How to hook managed API ?

涉及的Win32 API列表:

FlushInstructionCache、GetCurrentProcess、VirtualProtect、WriteProcessMemory

实战

下面是一段控制台程序的代码


namespace TestDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            byte[] byteArray = { 0xDE, 0xAD, 0xBE, 0xEF };
            string str = BitConverter.ToString(byteArray);
            Console.WriteLine(str);
            Console.ReadKey();
        }
    }
}

执行这段程序,我们可以得到如下输出

这段代码中我们将要hook的API为BitConverter.ToString。

编写Hook 代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace HookDemo
{
    public class MyAppDomainManager : AppDomainManager
    {
        public static int TestMethod(string param)
        {
            Debug.WriteLine("Hello .NET World! " + param);
            Patch();
            return 0;
        }

        public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
        {
            TestMethod("Go!");
            return;
        }

        public static string HookedMethod(byte[] value)
        {
            Debug.WriteLine("HookedMethod called");
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            string str = BitConverter.ToString(value, 0, value.Length);
            if(str == "62-D5-B7-A4-E0-89-72-D0-03-20-2C-6E-15-FA-3E-20")
            {
                str = "C7-65-65-DC-97-BA-24-84-9E-D9-AD-11-B9-4F-39-C9";
            }
            Debug.WriteLine(str);
            return str;
        }

        public static void Patch()
        {
            MethodInfo oridinal = typeof(BitConverter).GetMethod("ToString", new Type[] { typeof(byte[]) });
            MethodInfo replacement = typeof(MyAppDomainManager).GetMethod("HookedMethod", BindingFlags.Public | BindingFlags.Static);
            RuntimeHelpers.PrepareMethod(oridinal.MethodHandle);
            RuntimeHelpers.PrepareMethod(replacement.MethodHandle);

            IntPtr originalPtr = oridinal.MethodHandle.GetFunctionPointer();
            IntPtr replacementPtr = replacement.MethodHandle.GetFunctionPointer();

            byte[] patch = null;
            if(IntPtr.Size == 8)
            {
                patch = new byte[] { 0x49, 0xbb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x41, 0xff, 0xe3 };
                byte[] address = BitConverter.GetBytes(replacementPtr.ToInt64());
                for (int i = 0; i < address.Length; i++)
                {
                    patch[i + 2] = address[i];
                }
            }
            else
            {
                patch = new byte[] { 0x68, 0x0, 0x0, 0x0, 0x0, 0xc3 };
                byte[] address = BitConverter.GetBytes(replacementPtr.ToInt32());
                for (int i = 0; i < address.Length; i++)
                {
                    patch[i + 1] = address[i];
                }
            }

            uint oldprotect;
            if (!VirtualProtect(originalPtr, (UIntPtr)patch.Length, 0x40, out oldprotect))
            {
                throw new Win32Exception();
            }

            IntPtr written = IntPtr.Zero;
            if (!WriteProcessMemory(GetCurrentProcess(), originalPtr, patch, (uint)patch.Length, out written))
            {
                throw new Win32Exception();
            }

            //Flush insutruction cache to make sure our new code executes
            if (!FlushInstructionCache(GetCurrentProcess(), originalPtr, (UIntPtr)patch.Length))
            {
                throw new Win32Exception();
            }

            if (!VirtualProtect(originalPtr, (UIntPtr)patch.Length, oldprotect, out oldprotect))
            {
                throw new Win32Exception();
            }
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool FlushInstructionCache(IntPtr hProcess, IntPtr lpBaseAddress, UIntPtr dwSize);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetCurrentProcess();

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out IntPtr lpNumberOfBytesWritten);
    }
}

利用.NET 二进制携带的config文件实现DLL注入

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
    <runtime>
        <appDomainManagerAssembly value="HookDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        <appDomainManagerType value="HookDemo.MyAppDomainManager" />
    </runtime>
</configuration>

开启DbgView运行效果如下:

免费评分

参与人数 7威望 +1 吾爱币 +25 热心值 +6 收起 理由
hopecolor514 + 1 热心回复!
allspark + 1 + 1 我很赞同!
willJ + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
jy138290 + 1 + 1 谢谢@Thanks!
为之奈何? + 1 + 1 我很赞同!
helloworld0011 + 1 谢谢@Thanks!
JUNWO999 + 1 + 1 谢谢@Thanks!

查看全部评分

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

推荐
yanaying 发表于 2024-6-19 16:25
本帖最后由 yanaying 于 2024-6-19 16:35 编辑

appDomainManagerAssembly的文章我记得在2017年看过,当时也没太在意。
最近是不是被PYG弄得开始泛滥了,此类注入到处都是。

netcore中取消了应用程序域,没有这种手法了
3#
pizazzboy 发表于 2024-6-19 16:26
4#
wtujoxk 发表于 2024-6-19 19:25
yanaying 发表于 2024-6-19 16:25
appDomainManagerAssembly的文章我记得在2017年看过,当时也没太在意。
最近是不是被PYG弄得开始泛滥了, ...

用C++写劫持系统加载,加载后执行C#写的dll,不知道行不
5#
你好,再见 发表于 2024-6-19 20:06
支持一下大佬
6#
yanaying 发表于 2024-6-19 20:36
wtujoxk 发表于 2024-6-19 19:25
用C++写劫持系统加载,加载后执行C#写的dll,不知道行不

当然可以啊      
7#
rz66 发表于 2024-6-21 11:26
wtujoxk 发表于 2024-6-19 19:25
用C++写劫持系统加载,加载后执行C#写的dll,不知道行不

可以的,c++ hook ,调用 clr.dll
HMODULE clrModule = GetModuleHandle(L"clr.dll")
这里是调用 Framework4.0.3 32位
8#
wtujoxk 发表于 2024-6-21 13:40
rz66 发表于 2024-6-21 11:26
可以的,c++ hook ,调用 clr.dll
HMODULE clrModule = GetModuleHandle(L"clr.dll")
这里是调用 Frame ...

来个完整的示例
9#
hopecolor514 发表于 2024-6-23 16:27
谢谢大佬,好久不见,依然烧脑的代码
10#
renyxem 发表于 2024-11-20 20:30
感谢分享,学到很多知识,谢谢
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

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

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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