用c语言写易语言Linux库,【C语言】 用C写了个常用的代码注入库

[C] 纯文本查看 复制代码#include

#include

#include

#include "beaengine/BeaEngine.h"

#include "keystone/keystone.h"

#include "cheatlib.h"

HANDLE GetHandleByTitle(const char *pszTitle)

{

assert(pszTitle!=NULL);

HWND hWnd = FindWindow(NULL, pszTitle);

if(hWnd == 0){

return NULL;

}

DWORD dwPid = 0;

GetWindowThreadProcessId(hWnd, &dwPid);

return OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);

}

PDllInjectionInfo DllInjection(HANDLE hProcess, const char *pszLibFile)

{

assert(hProcess!=NULL && pszLibFile!=NULL);

// 计算dll名称大小

DWORD dwSize = (strlen(pszLibFile) + 1) * sizeof(char);

// 在远程进程中为dll名称分配空间

LPVOID pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);

if (pszLibFileRemote == NULL)

return NULL;

// 将DLL名称复制到远程进程地址空间

DWORD n = WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID)pszLibFile, dwSize, NULL);

if (n == 0)

return NULL;

// 从Kernel32.dll获取LoadLibraryA地址

PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");

if (pfnThreadRtn == NULL)

return NULL;

// 创建远程线程调用 LoadLibraryA(DLLPathname)

HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, pszLibFileRemote, 0, NULL);

if (hThread == NULL)

return NULL;

PDllInjectionInfo ptInfo = (PDllInjectionInfo)malloc(sizeof(DllInjectionInfo));

ptInfo->hProcess = hProcess;

ptInfo->hThread = hThread;

ptInfo->pszLibFileRemote = pszLibFileRemote;

return ptInfo;

}

void DllOutjection(PDllInjectionInfo ptInfo)

{

assert(ptInfo!=NULL);

//等待远程线程结束

WaitForSingleObject(ptInfo->hThread, INFINITE);

if (ptInfo->pszLibFileRemote != NULL)

VirtualFreeEx(ptInfo->hProcess, ptInfo->pszLibFileRemote, 0, MEM_RELEASE);

if (ptInfo->hThread != NULL)

CloseHandle(ptInfo->hThread);

free(ptInfo);

ptInfo = NULL;

}

static void IntToByte(int i, BYTE *bytes)

{

assert(bytes != NULL);

bytes[0] = (byte) (0xff & i);

bytes[1] = (byte) ((0xff00 & i) >> 8);

bytes[2] = (byte) ((0xff0000 & i) >> 16);

bytes[3] = (byte) ((0xff000000 & i) >> 24);

}

static void JmpBuilder(BYTE *pCmdOutput, DWORD dwTargetAddr, DWORD dwCurrentAddr)

{

assert(pCmdOutput != NULL);

pCmdOutput[0] = 0xE9;

DWORD jmpOffset = dwTargetAddr - dwCurrentAddr - 5;

IntToByte(jmpOffset, pCmdOutput+1);

}

static void FreeRequiredAsmInfo(PCheatLibRequiredAsmInfo ptInfo)

{

assert(ptInfo != NULL && ptInfo->pbOpCode != NULL);

free(ptInfo->pbOpCode);

ptInfo->pbOpCode = NULL;

free(ptInfo);

ptInfo = NULL;

}

static PCheatLibRequiredAsmInfo GetRequiredAsmInfo(HANDLE hProcess, LPVOID pAddress)

{

PCheatLibRequiredAsmInfo ptInfo = (PCheatLibRequiredAsmInfo)malloc(sizeof(CheatLibRequiredAsmInfo));

int nOpCodeSize = 32; // opcode的字节数

ptInfo->pbOpCode = (BYTE*)malloc(sizeof(BYTE)*nOpCodeSize);

DISASM disAsm;

memset(&disAsm, 0, sizeof disAsm);

ReadProcessMemory(hProcess, pAddress, (LPVOID)ptInfo->pbOpCode, nOpCodeSize, NULL);

disAsm.EIP = (UIntPtr)ptInfo->pbOpCode; // 保存opcode的缓冲区首地址

disAsm.VirtualAddr = (int)pAddress; // pbOpCode 指令的地址

disAsm.Archi = 32; // 32位

disAsm.Options = 0x000; // masm 汇编指令格式

int nCount = 0;// 用于记录在循环当中,反汇编了多少个字节

int nLen = 0 ; // 用于记录当前的汇编指令的字节数

// 调用Disasm()进行反汇编来获取指令长度

while(nCount < nOpCodeSize)

{

nLen = Disasm(&disAsm); // 每次只反汇编一条汇编指令, 并且返回当前得到的汇编指令的长度

if(nCount == 0){ // 获取第一条汇编指令大小

ptInfo->iFirstCmdSize = nLen;

}

nCount += nLen; // 累加已经反汇编的字节数

disAsm.EIP += nLen; // 定位到下一条汇编指令

disAsm.VirtualAddr += nLen; // 设置到下一条汇编指令的地址

if(nCount>=5)break; // 如果已经反汇编的字节数超过了jmp指令的字节数就不用继续分析了

}

ptInfo->iRequiredSize = nCount;

return ptInfo;

}

static void FreeAsmEncodeInfo(PCheatLibAsmEncodeInfo ptInfo)

{

// 如果反汇编错误那么pbOpCode会是NULL所以不能断言pbOpCode

assert(ptInfo != NULL);

if(ptInfo->pbOpCode != NULL)

ks_free(ptInfo->pbOpCode);

free(ptInfo);

ptInfo = NULL;

}

static PCheatLibAsmEncodeInfo EncodeAsm(const char *pszAsmCode, LPVOID pAddress)

{

// 根据pszAsmCode编译汇编代码

ks_engine *pengine = NULL;

if(KS_ERR_OK != ks_open(KS_ARCH_X86 , KS_MODE_32 , &pengine)){

return NULL;

}

PCheatLibAsmEncodeInfo ptInfo = (PCheatLibAsmEncodeInfo)malloc(sizeof(CheatLibAsmEncodeInfo));

ptInfo->pszAsmCode = pszAsmCode;

ptInfo->u64Address = (DWORD)pAddress;

int nRet = 0; // 保存函数的返回值,用于判断函数是否执行成功

nRet = ks_asm(pengine, /* 汇编引擎句柄,通过ks_open函数得到*/

pszAsmCode, /*要转换的汇编指令*/

(DWORD)pAddress, /*汇编指令所在的地址*/

&ptInfo->pbOpCode,/*输出的opcode*/

&ptInfo->nOpCodeSize,/*输出的opcode的字节数*/

&ptInfo->nCmdCount /*输出成功汇编的指令的条数*/

);

// 返回值等于-1时反汇编错误

if(nRet == -1) {

FreeAsmEncodeInfo(ptInfo);

return NULL;

}

// 关闭句柄

ks_close(pengine);

return ptInfo;

}

static void FreeCodeInjectionInfo(PCodeInjectionInfo ptInfo)

{

assert(ptInfo != NULL);

// 释放代码空间

if(ptInfo->pVirAddr != NULL){

VirtualFreeEx(ptInfo->hProcess, ptInfo->pVirAddr, 0, MEM_RELEASE);

}

FreeRequiredAsmInfo(ptInfo->ptRequiredAsmInfo);

free(ptInfo);

ptInfo = NULL;

}

PCodeInjectionInfo CodeInjection(HANDLE hProcess, LPVOID pAddress, const char *pszAsmCode)

{

// 在pAddress处收集必要的信息

PCheatLibRequiredAsmInfo ptRequiredAsmInfo = GetRequiredAsmInfo(hProcess, pAddress);

PCodeInjectionInfo ptCodeInjectionInfo = (PCodeInjectionInfo)malloc(sizeof(CodeInjectionInfo));

ptCodeInjectionInfo->hProcess = hProcess;

ptCodeInjectionInfo->pOrigAddr = pAddress;

ptCodeInjectionInfo->ptRequiredAsmInfo = ptRequiredAsmInfo;

DWORD WrittenLen = 0;

// 如果pszAsmCode是空字符串或NULL就使用nop填充该指令

if(pszAsmCode == NULL || strlen(pszAsmCode) == 0){

ptCodeInjectionInfo->pVirAddr = NULL;

BYTE *nopCode = (BYTE*)malloc(sizeof(BYTE)*ptRequiredAsmInfo->iFirstCmdSize);

memset(nopCode, 0x90, ptRequiredAsmInfo->iFirstCmdSize);

// 写入空指令

WriteProcessMemory(hProcess,

(LPVOID)pAddress,

nopCode,

ptRequiredAsmInfo->iFirstCmdSize,

&WrittenLen);

free(nopCode);

nopCode = NULL;

return ptCodeInjectionInfo;

}

// 开始构造我们自己的代码

// 我们不知道pszAsmCode中的汇编指令在函数申请的空间中会生成多少机器码

// 但使用这种方式计算出来的大小一定不会小于实际所需大小

int nCodeSize = strlen(pszAsmCode)+5;

// 在远程进程申请空间用于存放我们自己的代码

LPVOID virAddr = (PWSTR)VirtualAllocEx(hProcess,

NULL,

nCodeSize,

MEM_COMMIT,

PAGE_EXECUTE_READWRITE);

ptCodeInjectionInfo->pVirAddr = virAddr;

// 汇编pszAsmCode,需要virAddr来正确计算指令中的偏移

PCheatLibAsmEncodeInfo ptAsmCodeInfo = EncodeAsm(pszAsmCode, virAddr);

// 大概率是pszAsmCode有问题导致的

if(ptAsmCodeInfo == NULL){

FreeCodeInjectionInfo(ptCodeInjectionInfo);

return NULL;

}

BYTE *exeCode = (BYTE*)malloc(sizeof(BYTE)*(nCodeSize));

// 先使用nop填充

memset(exeCode, 0x90, nCodeSize);

// 将生成的汇编代码拷贝到exeCode中

memcpy(exeCode, ptAsmCodeInfo->pbOpCode, ptAsmCodeInfo->nOpCodeSize);

// 构建跳转指令

JmpBuilder(exeCode+ptAsmCodeInfo->nOpCodeSize,

(DWORD)pAddress+ptRequiredAsmInfo->iRequiredSize,

(DWORD)virAddr+ptAsmCodeInfo->nOpCodeSize);

// 把构建好的代码写入刚刚申请的空间中

WriteProcessMemory(hProcess, (LPVOID)virAddr, exeCode, nCodeSize, &WrittenLen);

free(exeCode);

exeCode = NULL;

FreeAsmEncodeInfo(ptAsmCodeInfo);

// 开始构造注入点跳转指令

BYTE *jmpCode = (BYTE*)malloc(sizeof(BYTE)*ptRequiredAsmInfo->iRequiredSize);

memset(jmpCode, 0x90, ptRequiredAsmInfo->iRequiredSize);

JmpBuilder(jmpCode, (DWORD)virAddr, (DWORD)pAddress);

// 向注入点写入跳转指令

WriteProcessMemory(hProcess,

(LPVOID)pAddress,

jmpCode,

ptRequiredAsmInfo->iRequiredSize,

&WrittenLen);

free(jmpCode);

jmpCode = NULL;

return ptCodeInjectionInfo;

}

void CodeOutjection(PCodeInjectionInfo ptInfo)

{

assert(ptInfo != NULL && ptInfo->ptRequiredAsmInfo != NULL);

DWORD WrittenLen = 0;

// 恢复原始代码

WriteProcessMemory(ptInfo->hProcess,

ptInfo->pOrigAddr,

ptInfo->ptRequiredAsmInfo->pbOpCode,

ptInfo->ptRequiredAsmInfo->iRequiredSize,

&WrittenLen);

FreeCodeInjectionInfo(ptInfo);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
========== 1.易支持机制 ========== !!!易支持信息、命令信息等等均使用某个结构储存!!!易源码中的自定义数据类型、类模块、组件即为支持中的定义数据类型!!!易语言 通过 GetNewInf() 获取支持信息!!!所以支持必须导出这个函数 ========== 2.支持命令调用 ========== !!!支持的命令调用方式也比较特殊!!!每个命令需要三个参数:返回值指针,参数数目,参数信息指针!!!做个一个定义数据类型的方法,每个方法的第一个参数为指向该对象的结构指针 ========== 3.简单说下易源码 ========== !!!易保存源码时没有保存各信息名称(比如命令名、数据类型名),而是保存了索引!!!所以支持内的各信息有必要时可以修改!!!但不要改动TA们的顺序,这会导致前期版本的源码出现问题 ========== 4.模版说明 ========== !!!本模版整天来说思路清晰,代码连小白都能理解!!!模版多数的参数使用通用型,使得模版简便!!!模版内没有多说废话, 直接把关键的过了一遍, 足够支持了!!!每条命令都演示了支持的各种操作,能想到的都先了!!!暂时没组件,目前没什么时间了,玩着电脑也冷~!!!尽量抽时间将组件的开发也模块化!!!或者各位有心人士可参考 e\sdk\cpp\samples\HtmlView 一下 ========== 5.关于静态 ========== !!!本人目前只做了动态,不做静态原因很多!!!本来打算做静态的,不过考虑到某些原因:!!!静态误报,动态转到静态时也会出现一些未知问题!!!个人也建议使用独立编译,5.3已经恢复!!!更建议用 黑月Cool编译!!!或者直接就是一个“懒”字!!!!各路有心人士可动手改一下!!!我也弄好了静态连接名的录入机制 ========== 6.为何选择支持 ========== !!!其实用模块扩展程序也是足够了!!!选择做支持还是安全的!!!而且支持有许多模块做不到的功能 ========== 7.关于易功能函数 ========== !!!顾名思义, 就是易内部提供给支持的函数!!!主要的用法呢还是得参考 lib2.h(位于 e\sdk\cpp\elib\lib.h)!!!虽说是一个C++头文件,但是语文好点、懂易语言就能理解!!!小学生的语文水平就差不多啦!!!我还是把一些常用到了 类_易功能 这个类里面!!!各位同学可以看看、 、 ========== 【最后】 ========== !!!直说:本人纯属菜鸟一枚, 各路大神勿喷即可 ==========??【信息】??========== !!!模版:易支持模版!!!作者:SalHe(Rabbit Group)!!!声明:大鸟勿喷即可!!!日期:2014年11月8日怎么编译我还是简单说一下,针对一下小白。编译的时候将文件名的后缀改为fne在放入易语言的支持目录就好了支持一发布后就不要修改数字签名和支持文件名了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值