A、分析API函数原理
B、自写API函数
C、SYSENTER指令
D、硬编码_emit
E、模拟FindWindow函数
课时:43
PUNICODE_STRING
MOV EAX,117A
7C92E510 > 8BD4 MOV EDX,ESP
7C92E512 0F34 SYSENTER
//取得RtlInitUnicodeString地址
typedef (__stdcall *PRtlInitUnicodeString)( PUNICODE_STRING , PCWSTR );
PRtlInitUnicodeString RtlInitUnicodeString;
RtlInitUnicodeString=(PRtlInitUnicodeString)GetProcAddress(GetModuleHandle("ntdll.dll"),"RtlInitUnicodeString");
//初始化PUNICODE_STRING字串结构 方法1
//pname->Buffer= wName ;
//pname->Length=wcslen(pname->Buffer)*2+1 ;
//UnsafeModuleName.MaximumLength=0x0fff;
//初始化PUNICODE_STRING字串结构 方法2
RtlInitUnicodeString(pname,wName);
=========================================================
笔记:
自写API函数,脱离动态链接库的限制.这样做的目地并不是用于过保护,而主要是用于隐藏我们自己的代码.
新建一个MFC程序,调用FandWindow函数,来查找计算器标题.用OD来跟踪一下执行过程,里面有一个CALL的调用,再继续跟踪又有一个CALL的调用,在里面没有直接发现对标题的读取,仔细查看发现是UNICODE代码,000E0006,E代表最大长度,6代表字个数,再看一下里面的数值就发现了宽字符的”计算器”;再继续向下跟就发现了117A的索引号,然后CALL到内核函数.ntdll.kiFastSystemCall.写上代码后总提示错误,应该是UNICODE字符没有定义的原因,到驱动代码中找到结构定义,然后又将函数中多余的__stdcall参数去掉,但是调用出错还是要用到__stdcall
///////////////////////////////myApi.h//////////////////////////
#pragma pack(1)
typedef struct _UNICODE_STRING { //因为不支持UNICODE所以要先定义结构
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING,*PUNICODE_STRING;
#pragma pack()
__declspec(naked) void sysFastCall() //模拟kiFastSystemCall 函数 以naked生成干净的汇编
{
__asm
{
// 7C92E510 > 8BD4 MOV EDX,ESP
//7C92E512 0F34 SYSENTER
mov edx,esp //因为不支持SYSENTER所以硬编码
__emit 0x0f
__emit 0x34
}
}
/*
77D28285 . FF75 18 PUSH DWORD PTR SS:[EBP+18] ; 0
77D28288 . FF75 E8 PUSH DWORD PTR SS:[EBP-18] ; PU_LCatipn
77D2828B . FF75 F8 PUSH DWORD PTR SS:[EBP-8] ; NULL
77D2828E . FF75 0C PUSH DWORD PTR SS:[EBP+C] ; 0
77D28291 . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; 0
77D28294 . E8 13450000 CALL USER32.77D2C7AC ; NtUserFindWindow
*/
__declspec(naked) HWND __stdcall My_FindWindow( //模拟上一层CALL
int p1,
int p2,
PUNICODE_STRING pu_classname,
PUNICODE_STRING pu_catption,
int p5)
{
__asm
{
MOV EAX,0x117A
call sysFastCall
RETN 0x14
}
}
///////////////////////////////////调用的代码 test_API.cpp///////////////////////
void CTest_APIDlg::OnButtonMyFindwindow()
{
UNICODE_STRING pu_className,pu_Caption; //定义字串
//调用驱动函数对字串进行初始化
typedef (__stdcall *PRtlInitUnicodeString)( PUNICODE_STRING , PCWSTR );
PRtlInitUnicodeString RtlInitUnicodeString;
RtlInitUnicodeString=(PRtlInitUnicodeString)GetProcAddress(GetModuleHandle("ntdll.dll"),"RtlInitUnicodeString");
RtlInitUnicodeString(&pu_className,L"SciCalc"); //类名
RtlInitUnicodeString(&pu_Caption,L"计算器"); //标题
HWND h=My_FindWindow(0,0,&pu_className,&pu_Caption,0);
::SendMessage(h,WM_CLOSE,0,0);
}
写好函数后用OD加载测试,确实已经过了OD的断点,另外NtProc.h里有关于SetWindowsHookEx的保护代码.
#include <string.h>
/*
0012F628 10000000 .... //hMod
0012F62C 0012F640 @?. //UnsafeModuleName
0012F630 00000000 ....//ThreadId
0012F634 00000002 ....//hookid =Wh_KeyBoard
0012F638 100010E0 ?.. GameDll.Gameproc //HookProc
0012F63C 00000002 .... //Ansi
0012F640 00660064 d.f.
0012F644 0012F678 x?. UNICODE "I:\\VC_Code\\PassNP_Code\\MFC_EXE\\Release\\GameDll.dll"
DWORD tid=0;
HMODULE hdll= LoadLibraryA("GameDll.dll");
HOOKPROC Gameproc=(HOOKPROC)GetProcAddress(hdll,"Gameproc");
Nt_SetWindowsHookEx(WH_KEYBOARD,Gameproc,::GetModuleHandle("GameDll.dll"),tid);
typedef struct _SetWindowsHookEx_Data
{
HINSTANCE hMod;
PUNICODE_STRING UnsafeModuleName;
DWORD ThreadId;
int HookId;
HOOKPROC HookProc;
BOOL Ansi;
}SetWindowsHookEx_Data;
*/
//#pragma pack(1)
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING,*PUNICODE_STRING;
//#pragma pack()
__declspec(naked) void sysCall()
{
_asm
{
__emit 0x8B
__emit 0xD4
__emit 0x0F
__emit 0x34
}
}
__declspec(naked) HHOOK __stdcall Nt_SetWindowsHookEx (HINSTANCE hMod, PUNICODE_STRING UnsafeModuleName, DWORD ThreadId, int HookId, HOOKPROC HookProc, BOOL Ansi)
{
_asm
{
MOV EAX,0x1225
call sysCall
retn 0x18
}
}
void My_SetWindowsHookEx()
{ //取得RtlInitUnicodeString地址
typedef (__stdcall *PRtlInitUnicodeString)( PUNICODE_STRING , PCWSTR );
PRtlInitUnicodeString RtlInitUnicodeString;
RtlInitUnicodeString=(PRtlInitUnicodeString)GetProcAddress(GetModuleHandle("ntdll.dll"),"RtlInitUnicodeString");
//
HINSTANCE hMod=LoadLibraryA("gamedll.dll");
UNICODE_STRING UnsafeModuleName;
PUNICODE_STRING pname=&UnsafeModuleName;
DWORD ThreadId=0;
int HookId=WH_KEYBOARD;
HOOKPROC Gameproc=(HOOKPROC)GetProcAddress(hMod,"Gameproc");
BOOL Ansi=2;
//初始化UnsafeModuleName 字串
WCHAR wName[256];
char Fullpath[256];
GetCurrentDirectory(256,Fullpath);
strcat(Fullpath, "\\gamedll.dll");//Fullpath=Fullpath+"gamedll.dll";
//把Fullpath 转换成 宽字符串
MultiByteToWideChar (CP_ACP, 0, Fullpath, -1, wName, sizeof(wName)*2+1);
//初始化PUNICODE_STRING字串结构 方法1
//pname->Buffer= wName ;
//pname->Length=wcslen(pname->Buffer)*2+1 ;
//UnsafeModuleName.MaximumLength=0x0fff;
//初始化PUNICODE_STRING字串结构 方法2
RtlInitUnicodeString(pname,wName);
// hMod=GetModuleHandle("GameDll.dll");
Nt_SetWindowsHookEx ( hMod, &UnsafeModuleName, ThreadId, HookId, Gameproc, Ansi);
}
__declspec(naked) HWND __stdcall Nt_FindWindow (int p1,int p2,PUNICODE_STRING p3_ClassName,PUNICODE_STRING p4_Caption, int p5)
{
__asm
{
mov eax,0x117a //NtUserFindWindowEx
call sysCall
retn 0x14
}
} |