这个方法的原理就是:
①首先在API头部写一个CC断点
②中断的时候程序收到消息,并且读出参数
需要注意的地方只有修正EIP寄存器,和读取参数的问题。
因为API采用STDCALL的方式调用,所以参数是从右向左压进堆栈的。
还有就是API的开头是
mov edi,edi
push ebp
mov ebp,esp
我们要注意,因为我们是在头部断下的,还没有执行push ebp,而执行了push ebp之后esp会减4,也就是说,我们在头部中断的时候要把esp-4才能拿ESP来读取参数!
还要注意的就是,如何不执行API直接跳转到返回地址,一般ESP储存的地址指向的就是返回地址,所以我们只要把EIP修改就好,如果你要设置返回值,那么就修改EAX为返回值。(记得修正ESP)
如何单步?这也是一个问题,我们可以在第一条指令中断之后,在第二条指令下CC断点,同时还原第一条指令,等到第二条指令触发中断事件时,我们再在第一条指令上下CC断点,再还原第二条指令,这就模拟了一次单步。
我把代码贴出来,使用VC2010编译
#include
#include
#define SE_DEBUG_PRIVILEGE 20
typedef DWORD(WINAPI *PRtlAdjustPrivilege) ///未文档化函数声明
(
ULONG Privilege,
BOOLEAN Enable,
BOOLEAN CurrentThread,
PBOOLEAN Enabled
);
void WINAPI AdjustPrivilege() ///ntdll中的提权函数
{
BOOLEAN Enabled;
PRtlAdjustPrivilege RtlAdjustPrivilege = (PRtlAdjustPrivilege)GetProcAddress(LoadLibrary((LPCSTR)"ntdll.dll"), "RtlAdjustPrivilege");
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &Enabled);
}
int main(void)
{
DWORD pid;
DWORD lpapi;
BYTE code[2];
BYTE _code;
BYTE cc = 0xCC;