记忆中的函数3

GetSartupInfo  获取一个进程的启动信息
参数表
参数 类型及说明
lpStartupInfo STARTUPINFO,指定一个STARTUPINFO结构,用于最终载入进程的启动信息

LoadLibraryA   
获取一个进程的启动信息 参数表 参数 类型及说明 lpStartupInfo STARTUPINFO,指定一个STARTUPINFO结构,用于最终载入进程的启动信
lstrcmpiA   


FreeLibrary       
释放指定的动态链接库,它们早先是用LoadLibrary API函数装载...对LoadLibrary的每一次调用都应该有一个对应
VirtualAllocEx
VirtualAllocEx 函数的作用是在指定进程的虚拟空间保留或提交内存区域,除非指定MEM_RESET参数,否则将该内存区域置0。
LPVOID VirtualAllocEx(
HANDLE hProcess, // 申请内存所在的进程句柄
LPVOID lpAddress, // 保留页面的内存地址;一般用NULL自动分配
SIZE_T dwSize, // 欲分配的内存大小,字节单位;注意实际分 配的内存大小是页内存大小的整数倍
DWORD flAllocationType,
DWORD flProtect
);


WriteProcessMemory         
WriteProcessMemory

VB函数原型:
Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

作用:写内存

说明:
hProcess ,   进程的句柄   
   
lpBaseAddress,   进程地址   
   
lpBuffer,   数据存放地址   
   
nSize,   数据的长度   
   
lpNumberOfBytesWritten,实际数据的长度


GetModuleHandleA      

CreateRemoteThread和WriteProcessMemory技术

示例程序:WinSpy

另一种注入代码到其他进程地址空间的方法是使用WriteProcessMemory API。这次你不用编写一个独立的DLL而是直接复制你的代码到远程进程(WriteProcessMemory)并用CreateRemoteThread执行之。

让我们看一下CreateRemoteThread的声明:
HANDLE CreateRemoteThread(
   HANDLE hProcess,         // handle to process to create thread in
   LPSECURITY_ATTRIBUTES lpThreadAttributes,   // pointer to security
                                              // attributes
   DWORD dwStackSize,       // initial thread stack size, in bytes
   LPTHREAD_START_ROUTINE lpStartAddress,      // pointer to thread
                                              // function
   LPVOID lpParameter,      // argument for new thread
   DWORD dwCreationFlags,   // creation flags
   LPDWORD lpThreadId       // pointer to returned thread identifier
);


和CreateThread相比,有一下不同:
●增加了hProcess参数。这是要在其中创建线程的进程的句柄。
●CreateRemoteThread的lpStartAddress参数必须指向远程进程的地址空间中的函数。这个函数必须存在于远程进程中,所以我们不能简单地传递一个本地ThreadFucn的地址,我们必须把代码复制到远程进程。
●同样,lpParameter参数指向的数据也必须存在于远程进程中,我们也必须复制它。


现在,我们总结一下使用该技术的步骤:
1.   得到远程进程的HANDLE(OpenProcess)。
2.   在远程进程中为要注入的数据分配内存(VirtualAllocEx)、
3.   把初始化后的INJDATA结构复制到分配的内存中(WriteProcessMemory)。
4.   在远程进程中为要注入的数据分配内存(VirtualAllocEx)。
5.   把ThreadFunc复制到分配的内存中(WriteProcessMemory)。
6.   用CreateRemoteThread启动远程的ThreadFunc。
7.   等待远程线程的结束(WaitForSingleObject)。
8.   从远程进程取回指执行结果(ReadProcessMemory 或 GetExitCodeThread)。
9.   释放第2、4步分配的内存(VirtualFreeEx)。
10.   关闭第6、1步打开打开的句柄。

另外,编写ThreadFunc时必须遵守以下规则:
1.   ThreadFunc不能调用除kernel32.dll和user32.dll之外动态库中的API函数。只有kernel32.dll和 user32.dll(如果被加载)可以保证在本地和目的进程中的加载地址是一样的。(注意:user32并不一定被所有的Win32进程加载!)参考附 录A。如果你需要调用其他库中的函数,在注入的代码中使用LoadLibrary和GetProcessAddress强制加载。如果由于某种原因,你需 要的动态库已经被映射进了目的进程,你也可以使用GetMoudleHandle代替LoadLibrary。同样,如果你想在ThreadFunc中调 用你自己的函数,那么就分别复制这些函数到远程进程并通过INJDATA把地址提供给ThreadFunc。

2.   不要使用static字符串。把所有的字符串提供INJDATA传递。为什么?编译器会把所有的静态字符串放在可执行文件的“.data”段,而仅仅在代 码中保留它们的引用(即指针)。这样,远程进程中的ThreadFunc就会执行不存在的内存数据(至少没有在它自己的内存空间中)。

3.   去掉编译器的/GZ编译选项。这个选项是默认的(看附录B)。
4.   要么把ThreadFunc和AfterThreadFunc声明为static,要么关闭编译器的“增量连接(incremental linking)”(看附录C)。
5.   ThreadFunc中的局部变量总大小必须小于4k字节(看附录D)。注意,当degug编译时,这4k中大约有10个字节会被事先占用。
6.   如果有多于3tch分支的case语句,必须像下面这样分割开,或用if-else if代替.

     case constant1: statement1; goto END;
     case constant2: statement2; goto END;
     case constant3: statement2; goto END;
}

     case constant4: statement4; goto END;
     case constant5: statement5; goto END;
     case constant6: statement6; goto END;
}
END:

kernel32     






GetProcAddress     函数功能描述:
GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。
函数原型:
FARPROC GetProcAddress(
  HMODULE hModule,    // DLL模块句柄
  LPCSTR lpProcName   // 函数名
);
参数:
hModule
  [in] 包含此函数的DLL模块的句柄。LoadLibrary或者GetModuleHandle函数可以返回此句柄。
lpProcName
  [in] 包含函数名的以NULL结尾的字符串,或者指定函数的序数值。如果此参数是一个序数值,它必须在一个字的底字节,高字节必须为0。
返回值:
  如果函数调用成功,返回值是DLL中的输出函数地址。
  如果函数调用失败,返回值是NULL。得到进一步的错误信息,调用函数GetLastError。
注释:
  GetProcAddress函数被用来检索在DLL中的输出函数地址。
  lpProcName指针指向的函数名,拼写和大小写必须和DLL源代码中的模块定义文件(.DEF)中输出段(EXPORTS)中指定的相同。 Win32 API函数的输出名可能不同于你在代码中调用的这些函数名,这个不同被宏隐含在相关的SDK头文件中。如果想得到更多信息,请参考Win32函数原型 (Win32 Function Prototypes)。
  lpProcName参数能够识别DLL中的函数,通过指定一个与函数相联系的序数值(在.DEF中的EXPORTS段)。 GetProcAddress函数验证那个指定的序数值是否在输出的序数1和最高序数值之间(在.DEF中)。函数用这个序数值作为索引从函数表中读函数 地址,假如.DEF 文件不连续地定义函数的序数值,如从1到N(N是输出的函数序数值),错误将会发生,GetProcAddress将会返回一个错误的、非空的地址,虽然 指定的序数没有对应的函数。
  为了防止函数不存在,函数应该通过名字指定而不是序数值。
要求:
  Windows NT/2000: 要求Windows NT 3.1 或以后版本。
  Windows 95/98: 要求Windows 95 或以后版本。
  头文件: 在Winbase.h中声明,include Windows.h。
  库文件: Use Kernel32.lib。
参看:
动态链接库纵览(Dynamic-Link Libraries Overview), 动态链接库函数(Dynamic-Link Library Functions),FreeLibrary, GetModuleHandle, LoadLibrary
示例代码:
  调用KERNEL32.DLL中的RegisterServiceProcess(仅在Windows98中适用)
  HMODULE hModule=GetModuleHandle("kernel32.dll");
  if (hModule)
  {
     typedef DWORD (CALLBACK *LPFNREGISTER)(DWORD,DWORD);
     LPFNREGISTER lpfnRegister;
     lpfnRegister=(LPFNREGISTER)GetProcAddress(hModule,"RegisterServiceProcess");
     if (lpfnRegister)
     {
       (*lpfnRegister)(NULL,1L);
     }
  }


            












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值