12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 297|回复: 0

代码注入

[复制链接]
发表于 2021-2-19 17:53:54 | 显示全部楼层 |阅读模式
简介

代码注入在分析程序或制作外挂外挂时优劣常爱使用的一种本领, 通常用于调用程序功能, 好比调用程序中的call;其基本原理和DLL注入的原理一样, 目前已经有许多工具可以直接实当代码注入或DLL注入了, 本文只是学习一下原理....
思绪

思绪很简朴, 基本就两大步:

  • OpenProcess打开需要注入的程序, 获取句柄;
  • 通过CreateRemoteThread函数将我们需要注入的代码以新的线程的方式进行运行, 到达注入的效果;
通过PEB获取模块基址

通常我们注入的代码一般都是汇编, 假如注入是很复杂的代码, 我们通常将代码写到DLL中, 直接用DLL注入了;
所以为了使我们的汇编根据有健壮性, 这里说一下如何用汇编获取程序模块的基地址, 注入的代码就相当于是写shellcode;
PEB

在fs:[0x30]地址处保存着一个指针, 指向了PEB布局, 布局基本如下:
typedef struct _PEB { // Size: 0x1D8/*000*/ UCHAR InheritedAddressSpace;/*001*/ UCHAR ReadImageFileExecOptions;/*002*/ UCHAR BeingDebugged;/*003*/ UCHAR SpareBool; // Allocation size/*004*/ HANDLE Mutant;/*008*/ HINSTANCE ImageBaseAddress; // Instance/*00C*/ VOID *DllList;  //_PEB_LDR_DATA        ;进程加载的模块链表/*010*/ PPROCESS_PARAMETERS *ProcessParameters;/*014*/ ULONG SubSystemData;/*018*/ HANDLE DefaultHeap;/*01C*/ KSPIN_LOCK FastPebLock;/*020*/ ULONG FastPebLockRoutine;/*024*/ ULONG FastPebUnlockRoutine;/*028*/ ULONG EnvironmentUpdateCount;/*02C*/ ULONG KernelCallbackTable;/*030*/ LARGE_INTEGER SystemReserved;/*038*/ ULONG FreeList;/*03C*/ ULONG TlsExpansionCounter;/*040*/ ULONG TlsBitmap;/*044*/ LARGE_INTEGER TlsBitmapBits;/*04C*/ ULONG ReadOnlySharedMemoryBase;/*050*/ ULONG ReadOnlySharedMemoryHeap;/*054*/ ULONG ReadOnlyStaticServerData;/*058*/ ULONG AnsiCodePageData;/*05C*/ ULONG OemCodePageData;/*060*/ ULONG UnicodeCaseTableData;/*064*/ ULONG NumberOfProcessors;/*068*/ LARGE_INTEGER NtGlobalFlag;/*070*/ LARGE_INTEGER CriticalSectionTimeout;/*078*/ ULONG HeapSegmentReserve;/*07C*/ ULONG HeapSegmentCommit;/*080*/ ULONG HeapDeCommitTotalFreeThreshold;/*084*/ ULONG HeapDeCommitFreeBlockThreshold;/*088*/ ULONG NumberOfHeaps;/*08C*/ ULONG MaximumNumberOfHeaps;/*090*/ ULONG ProcessHeaps;/*094*/ ULONG GdiSharedHandleTable;/*098*/ ULONG ProcessStarterHelper;/*09C*/ ULONG GdiDCAttributeList;/*0A0*/ KSPIN_LOCK LoaderLock;/*0A4*/ ULONG OSMajorVersion;/*0A8*/ ULONG OSMinorVersion;/*0AC*/ USHORT OSBuildNumber;/*0AE*/ USHORT OSCSDVersion;/*0B0*/ ULONG OSPlatformId;/*0B4*/ ULONG ImageSubsystem;/*0B8*/ ULONG ImageSubsystemMajorVersion;/*0BC*/ ULONG ImageSubsystemMinorVersion;/*0C0*/ ULONG ImageProcessAffinityMask;/*0C4*/ ULONG GdiHandleBuffer[0x22];/*14C*/ ULONG PostProcessInitRoutine;/*150*/ ULONG TlsExpansionBitmap;/*154*/ UCHAR TlsExpansionBitmapBits[0x80];/*1D4*/ ULONG SessionId;} PEB, *PPEB;PEB布局的偏移0xc处保存着另外一个指针ldr,该指针为PEB_LDR_DATA:
PEB_LDR_DATA

typedef struct _PEB_LDR_DATA{ ULONG Length; // +0x00 BOOLEAN Initialized; // +0x04 PVOID SsHandle; // +0x08 LIST_ENTRY InLoadOrderModuleList; // +0x0c LIST_ENTRY InMemoryOrderModuleList; // +0x14 LIST_ENTRY InInitializationOrderModuleList;// +0x1c} PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24PEB_LDR_DATA布局的后三个成员是指向LDR_MODULE链表布局中相应三条双向链表头的指针, 分别是按照加载序次, 在内存中地址序次和初始化序次分列的模块信息布局的指针, 其中LDR_MODULE布局就是_LDR_DATA_TABLE_ENTRY布局; 而链表的第一个就保存了当前程序的基地址;
_LDR_DATA_TABLE_ENTRY布局

typedef struct _LDR_DATA_TABLE_ENTRY  {      LIST_ENTRY InLoadOrderLinks;  // +0x00    LIST_ENTRY InMemoryOrderLinks;  // +0x04    LIST_ENTRY InInitializationOrderLinks;  // +0x08    PVOID DllBase;  // +0x0c    PVOID EntryPoint;  // +0x10    DWORD SizeOfImage;      UNICODE_STRING FullDllName;      UNICODE_STRING BaseDllName;      DWORD Flags;      WORD LoadCount;      WORD TlsIndex;      LIST_ENTRY HashLinks;      PVOID SectionPointer;      DWORD CheckSum;      DWORD TimeDateStamp;      PVOID LoadedImports;      PVOID EntryPointActivationContext;      PVOID PatchInformation;  }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;  其中偏移为0x10的位置的EntryPoint就保存了模块的基地址;
综上所述, 我们可以利用一下这段汇编代码获取程序的基地址:
        mov eax, fs:[0x30];     // PEB        mov ebx, [eax + 0xc];   // PEB_LDR_DATA        mov eax, [ebx + 0x14];  // InMemoryOrderModuleList        mov ebx, [eax + 0x10];  // ebx = EntryPoint(基址)假如在DLL当中获取程序基地址, 可以使用下面的代码:
void Get_addr(DWORD pro_id){    HANDLE hpro = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pro_id);        if (hpro == 0){            printf("无法获取进程句柄");        }        printf("进程句柄id: %d\n",hpro);        // 获取每一个模块加载基址        DWORD pro_base = NULL;        HMODULE hModule[100] = {0};        DWORD dwRet = 0;        int num = 0;        int bRet = EnumProcessModulesEx(hpro, (HMODULE *)(hModule), sizeof(hModule),&dwRet,NULL);        if (bRet == 0){            printf("EnumProcessModules");        }        // 总模块个数        num = dwRet/sizeof(HMODULE);        printf("总模块个数: %d\n",num);        // 打印每一个模块加载基址        char lpBaseName[100];        for(int i = 0;i
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-4-20 18:24 , Processed in 0.125000 second(s), 30 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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