HWND hWnd=::FindWindow(_T("SciCalc"),_T("计算器")); ::SendMessage(hWnd,WM_CLOSE,NULL,NULL);
为了方便分析参数,给FindWindow也传递了类名。
OD载入,bp FindWindowW,运行后断下来,来到FindWindowW里面
77D2C9C5 55 PUSH EBP
77D2C9C6 8BEC MOV EBP,ESP
77D2C9C8 33C0 XOR EAX,EAX
77D2C9CA 50 PUSH EAX
77D2C9CB FF75 0C PUSH DWORD PTR SS:[EBP+C]
77D2C9CE FF75 08 PUSH DWORD PTR SS:[EBP+8]
77D2C9D1 50 PUSH EAX
77D2C9D2 50 PUSH EAX
77D2C9D3 E8 8AFFFFFF CALL USER32.77D2C962
77D2C9D8 5D POP EBP
77D2C9D9 C2 0800 RETN 8
FindWindowW里面其实又调用了USER32!InternalFindWindowExW,这个函数接收5个参数,第三个是类名,第四个是标题,其他参数不用管,跟进去看下
77D2C964 55 PUSH EBP
77D2C965 8BEC MOV EBP,ESP
77D2C967 83EC 20 SUB ESP,20
77D2C96A 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10]
77D2C96D 56 PUSH ESI
77D2C96E 8B35 D814D177 MOV ESI,DWORD PTR DS:[<&ntdll.RtlInitUni>; ntdll.RtlInitUnicodeString
77D2C974 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
77D2C977 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
77D2C97A 57 PUSH EDI
77D2C97B 33FF XOR EDI,EDI
77D2C97D A9 0000FFFF TEST EAX,FFFF0000
77D2C982 897D EC MOV DWORD PTR SS:[EBP-14],EDI
77D2C985 897D FC MOV DWORD PTR SS:[EBP-4],EDI
77D2C988 0F84 F0540000 JE USER32.77D31E7E
77D2C98E 50 PUSH EAX
77D2C98F 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10]
77D2C992 50 PUSH EAX
77D2C993 FFD6 CALL ESI
77D2C995 FF75 14 PUSH DWORD PTR SS:[EBP+14]
77D2C998 8D45 E0 LEA EAX,DWORD PTR SS:[EBP-20]
77D2C99B 50 PUSH EAX
77D2C99C 897D EC MOV DWORD PTR SS:[EBP-14],EDI
77D2C99F 8945 E8 MOV DWORD PTR SS:[EBP-18],EAX
77D2C9A2 FFD6 CALL ESI
77D2C9A4 FF75 18 PUSH DWORD PTR SS:[EBP+18]
77D2C9A7 FF75 E8 PUSH DWORD PTR SS:[EBP-18]
77D2C9AA FF75 F8 PUSH DWORD PTR SS:[EBP-8]
77D2C9AD FF75 0C PUSH DWORD PTR SS:[EBP+C]
77D2C9B0 FF75 08 PUSH DWORD PTR SS:[EBP+8]
77D2C9B3 E8 F4FDFFFF CALL USER32.77D2C7AC
77D2C9B8 5F POP EDI
77D2C9B9 5E POP ESI
77D2C9BA C9 LEAVE
77D2C9BB C2 1400 RETN 14这里面调用的是USER32!NtUserFindWindowEx,这个函数也是接收5个参数,第三个是类名,第四个是标题,其他参数同样不用管,不过这里为什么实际数据跟堆栈中不同呢,例如第三个参数PUSH DWORD PTR SS:[EBP-8],堆栈中类名的位置明明是EBP-C的啊。。。汇编菜鸟请指教
继续跟进去,就看到熟悉的系统调用了
77D2C7AC B8 7A110000 MOV EAX,117A
77D2C7B1 BA 0003FE7F MOV EDX,7FFE0300
77D2C7B6 FF12 CALL DWORD PTR DS:[EDX]
77D2C7B8 C2 1400 RETN 14
7C92E510 > 8BD4 MOV EDX,ESP
7C92E512 0F34 SYSENTER
7C92E514 > C3 RETN
我们其实要做的就是模拟NtUserFindWindowEx这个函数,直接上代码
#pragma pack(1)
typedef struct _UNICODE_STRING{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING,*PUNICODE_STRING;
#pragma pack()
typedef VOID (__stdcall *PRtlInitUnicodeString)(IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString);
PRtlInitUnicodeString RtlInitUnicodeString=(PRtlInitUnicodeString)GetProcAddress(GetModuleHandle(_T("ntdll.dll")),"RtlInitUnicodeString");
__declspec(naked) VOID __stdcall kiFastSystemCall()//模拟kiFastSystemCall
{
__asm
{
mov edx,esp;
_EMIT 0x0F
_EMIT 0x34
}
}
__declspec(naked) HWND __stdcall MyFindWindow(int a,
int b,
PUNICODE_STRING puClassName,
PUNICODE_STRING puCaption,
int d
)
{
__asm
{
mov eax,0x117A;
call kiFastSystemCall;
retn 0x14;
}
}调用
UNICODE_STRING pu_className,pu_Caption;
RtlInitUnicodeString(&pu_className,_T("SciCalc"));
RtlInitUnicodeString(&pu_Caption,_T("计算器"));
HWND hWnd=MyFindWindow(NULL,NULL,&pu_className,&pu_Caption,NULL);
::SendMessage(hWnd,WM_CLOSE,NULL,NULL);
注意需要导出下RtlInitUnicodeString用它来初始化字符串传参
另外跟这个函数时,这个函数内部调用的函数名是看不到的,可以拿到已经加载好符号的WINDBG中去查看
同样bp user32!FindWindowW跟几步就看到了