能力值:
( LV2,RANK:10 )
|
-
-
2 楼
没有人指点我,我也不知道怎么弄,自己瞎看瞎弄,
试了直接读User32然后复制到内存中,改了重定位和输出表,调用MessagboxA就出个框,连"确定"和"取消"都显示不出来,全是白板按钮.
又试了在内存中把原来的User32复制到新的内存调用MessagboxA,看起来一切正常,和普通调用没区别了,但是调用其他复杂点的函数都不能成功,尝试调用了EnumDesktopWindows,连回调函数都进不去.
整个论坛都搜索完了,挺多自己加载PE的,但是都是用MessagboxA做例子,换个其他函数的话论坛上说的方法全部歇菜(我指的是PELOAD的方法),
都说是老技术了,那么多人在用了,怎么就没人舍得说一下呢
|
能力值:
( LV5,RANK:60 )
|
-
-
3 楼
不知道楼主的汇编到底怎样,但是如果汇编不好,一定先学好,然后看楼主这个问题的意思是把系统dll复制改名到自己的文件夹下用loadlibrary和getprocaddr来调用函数?不知道楼主对pe文件格式的理解怎么样,pe文件中有导出表,是用一个image_export_directory来描述的,如果楼主对我上面两句话觉得一头雾水,请在学好汇编的前提下看一看windows pe权威指南这本书,如果没有这些基础知识,即使你解决了问题,都不知道到底是怎么解决的。
楼主提问请把情况说的详细些,不是不回答你,我并不确定我知道你在问什么。
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
你好,非常感谢你的回答,可能我的问题不清楚,给大家添麻烦了.
我的问题本意是,想加载一些系统DLL,比如说我加载一份ntdll模块,通过自己加载的模块调用函数,而不通过系统加载的模块.这样可能会安全一点,最后我做了些尝试,把ntdll复制到内存中来,修改了重定位和导出函数表,但是调用自己加载模块里的函数时往往不能成功,不过一些简单点的函数还是能成功的,例如:MessageBoxA这个,其它函数就不能成功了.
我这人是比较没创造力的人,所以想请大家告诉我还差什么,
|
能力值:
( LV5,RANK:60 )
|
-
-
5 楼
首先,MessageBoxA这个函数是在user32.dll中的,而不是ntdll.dll中,再然后,看你的描述,你是把dll文件改名后直接映射到内存的?pe文件的内存映射文件和被加载器加载到内存中的组织形式有很大不同(我对这点不是很清楚),如果你是直接将文件放到内存里,只怕简单的修改重定位和导出表不能让你正确的调用里面的函数。
我做了一下测试,我先把ntdll.dl文件复制到程序在的文件夹下然后改名为myntdll.dll,然后在程序中直接使用HMODULE hNtDll = LoadLibraryA("myntdll.dll"),然后使用GetProcAddress(hNtDll,"ZwQuerySystemInformation")可以成功返回函数地址并调用成功。全部程序代码:(稍微修改网上的枚举进程的程序)
#include <windows.h>
#include <ntsecapi.h>
#include <stdio.h>
typedef DWORD (WINAPI *ZWQUERYSYSTEMINFORMATION)(DWORD, PVOID, DWORD, PDWORD);
typedef struct _SYSTEM_PROCESS_INFORMATION
{
DWORD NextEntryDelta;
DWORD ThreadCount;
DWORD Reserved1[6];
FILETIME ftCreateTime;
FILETIME ftUserTime;
FILETIME ftKernelTime;
UNICODE_STRING ProcessName;
DWORD BasePriority;
DWORD ProcessId;
DWORD InheritedFromProcessId;
DWORD HandleCount;
DWORD Reserved2[2];
DWORD VmCounters;
DWORD dCommitCharge;
PVOID ThreadInfos[1];
}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
#define SystemProcessesAndThreadsInformation 5
void main()
{
HMODULE hNtDll = LoadLibraryA("myntdll.dll");
if(!hNtDll)
return;
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll,"ZwQuerySystemInformation");
ULONG cbBuffer = 0x10000;
LPVOID pBuffer = NULL;
pBuffer = malloc(cbBuffer);
if(pBuffer == NULL)
return;
ZwQuerySystemInformation(SystemProcessesAndThreadsInformation,pBuffer,cbBuffer,NULL);
PSYSTEM_PROCESS_INFORMATION pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;
for(;;)
{
wprintf(L"PID: %d (%ls) ",pInfo->ProcessId,pInfo->ProcessName.Buffer);
if(pInfo->NextEntryDelta == 0)
break;
pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo) + pInfo->NextEntryDelta);
}
free(pBuffer);
getchar();
}
编译链接后运行效果:
我实在不理解你到底是在做什么,也许我对你的目的理解有误,你能不能上传一部分代码?
祝你尽快解决问题,我也只是一个小小菜鸟
PS:我不是用的VC,用的GCC编译链接,这应该不是主要问题。
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
谢谢你的回答,让我心里倍感温暖,我的本意是想自己加载ntdll并调用里面的函数,而不通过系统加载的ntdll 这样可以轻度的减少一些对函数的hook,我知道哪怕自己加载ntdll在R3上就算要hook也是可以的,但是能减少一些是一些,能好一点点是一点点,所以我想自己加载ntdll调用,这样别人hook系统加载的ntdll就没有效果了,我还想禁止线程的创建和不停的安装调试钩子来防止别人注入代码,因为按照我自己的理解注入代码和模块都要创建线程,不然怎么启动呢.
我知道很多人能够办到,但是自己能力太差遇到了麻烦,搜索了很多资料后觉得是写一个PE加载器能够办到驱动和dll的自加载.原理还是比较简单,我了解就是通过加载目标dll或者直接读盘符上的文件,复制到内存中,然后修改输出表和重定位,论坛有几篇帖子有介绍,但是都差不多,大致的代码基本如下面:
HMEMORYMODULE MyLoadLibrary(const void *data)
{
PMEMORYMODULE result;
PIMAGE_DOS_HEADER dos_header;
PIMAGE_NT_HEADERS old_header;
unsigned char *code, *headers;
SIZE_T locationDelta;
DllEntryProc DllEntry;
BOOL successfull;
dos_header = (PIMAGE_DOS_HEADER)data;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
return NULL;
}
old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew];
if (old_header->Signature != IMAGE_NT_SIGNATURE) {
return NULL;
}
code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),
old_header->OptionalHeader.SizeOfImage,
MEM_RESERVE,
PAGE_READWRITE);
if (code == NULL) {
code = (unsigned char *)VirtualAlloc(NULL,
old_header->OptionalHeader.SizeOfImage,
MEM_RESERVE,
PAGE_READWRITE);
if (code == NULL) {
return NULL;
}
}
result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), 0, sizeof(MEMORYMODULE));
result->codeBase = code;
result->numModules = 0;
result->modules = NULL;
result->initialized = 0;
VirtualAlloc(code,
old_header->OptionalHeader.SizeOfImage,
MEM_COMMIT,
PAGE_READWRITE);
headers = (unsigned char *)VirtualAlloc(code,
old_header->OptionalHeader.SizeOfHeaders,
MEM_COMMIT,
PAGE_READWRITE);
memcpy(headers, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders);
result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew];
result->headers->OptionalHeader.ImageBase = (POINTER_TYPE)code;
CopySections(data, old_header, result);
locationDelta = (SIZE_T)(code - old_header->OptionalHeader.ImageBase);
if (locationDelta != 0) {
PerformBaseRelocation(result, locationDelta);
}
if (!BuildImportTable(result)) {
goto error;
}
FinalizeSections(result);
if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) {
DllEntry = (DllEntryProc) (code + result->headers->OptionalHeader.AddressOfEntryPoint);
if (DllEntry == 0) {
goto error;
}
successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
if (!successfull) {
goto error;
}
result->initialized = 1;
}
return (HMEMORYMODULE)result;
error:
MyFreeLibrary(result);
return NULL;
}
我用PE加载的方式加载自己写的dll是可以成功的,哪怕是加载user32这样的模块调用MessageBoxA这样的函数也是可以成功的,
但是我调用我认为稍微复杂一些的函数,例如EnumDesktopWindows的时候,却不能进到我设的回调函数里面,很是奇怪.我个人资质比较差,看到汇编代码那样比较带联想性的代码,我总是不能把它转成C++代码,基本能看懂,但是不知道意思是什么,好像英语里面能看懂26个字母,但是字母组成的单词句子我就不知道什么意思了,所以那么久我也基本只能看懂c++代码
|