发信人: wenbobo(灌了拂衣去)
整理人: wenbobo(2002-12-06 23:30:34), 站内信件
|
文章虽不是原创,至少也是我翻译的,请大家转载时注明出处。
原作者:Sergey Karyshev([email protected])
原文发表于:www.codeguru.com
Windows 95 最后的秘密暴光了!
一个关于Windows95问得最多的问题是“资源管理器是如何得到系统资源使用状况的”?
微软文档表明GetFreeSystemResources函数在Win32中被停止使用了.Win32文档也说现在系统资源实际上是无限.但是资源管理器的关于对话框提示这种说法是不恰当的(至少对Windows95)。我还没有测验过Windows98但我相信文档对于WindowsNT来说是恰当.但是,对于Windows95,他们的文档肯定搞错了.[main注:其实95/OSR2/98/se/me都一样]
16位模块USER.EXE在Windows95中仍然存在,并且16位的应用程序能通过16位的函数GetFreeSystemResources来找到系统资源信息.那样,为什么资源管理器(或者任何32位应用程序)不能也这样调用呢?
下面代码片段展示了Win32程序如何调用16位DLL里的API函数。请注意GetK32ProcAddress函数由Andrew Schulman的“Unauthorized Windows 95 Update”提供。为了满足你的好奇心,这里提供这个函数的头文件和实现部分的链接:
http://ftp.uni-mannheim.de/info/OReilly/windows/win95.update/k32exp.c
http://ftp.uni-mannheim.de/info/OReilly/windows/win95.update/k32exp.h
[main注:我会在后面附上这两个文件的]
(因为k32exp.c是作为一独立模块的,我猜测它是被版权保护的)
WORD GetFreeSystemResources(WORD type)
{
//Decarations "c" style
typedef HINSTANCE (WINAPI* LOADLIB16)(char*);
typedef LONG (WINAPI* GETPROC16)(HINSTANCE, LPCSTR);
typedef BOOL (WINAPI* FREELIB16)(HINSTANCE);
FARPROC QT_Thunk;
LOADLIB16 pLoadLib16;
GETPROC16 pGetProc16;
FREELIB16 pFreeLib16;
HINSTANCE hInst;
DWORD pGetRes;
WORD user_fsr;
WORD _type;
HMODULE hKernel;
//Usuall Windows API calls
hKernel = GetModuleHandle("KERNEL32");
QT_Thunk = GetProcAddress(hKernel, "QT_Thunk");
//Andrew Schulman's
pLoadLib16 = (LOADLIB16) GetK32ProcAddress(LOADLIBRARY16_ORD);
pGetProc16 = (GETPROC16) GetK32ProcAddress(GETPROCADDRESS16_ORD);
pFreeLib16 = (FREELIB16) GetK32ProcAddress(FREELIBRARY16_ORD);
//Usuall for "c"-style calls - by pointer to function
hInst = (*pLoadLib16)("user");
(*pFreeLib16)(hInst);
pGetRes = (*pGetProc16)(hInst,"GetFreeSystemResources");
//How to call 16-bit dll API from 32-bit .exe using QT_Thunk function
_type = type;
if (pGetRes)
_asm
{
push _type
mov edx, [pGetRes]
call QT_Thunk
mov [user_fsr], ax
}
return user_fsr;
}
文中的演示是一个要取得Windows95的剩余系统资源的控制台程序。可以简单的从控制台编译它。
你怎么知道Windows95资源管理器使用16位的USER.EXE得到剩余系统资源的?只需要请求你的黑客好朋友在USER.EXE让GetFreeSystemResources函数返回0然后再看看资源管理器显示的剩余系统资源是多少!在我的4.00.950版本的USER.EXE中,GetFreeSystemResources从偏移地址0x444FF开始.
[main注:用IDA修改,选择patch功能,打入汇编代码ret 0]
[main注:方便大家,我把相关文件附在这里]
[这是主程序]
#include <windows.h>
#include "k32exp.h"
#include "stdio.h" //for printf only
// From 16-bit windows.h
#define GFSR_SYSTEMRESOURCES 0
#define GFSR_GDIRESOURCES 1
#define GFSR_USERRESOURCES 2
//Forward declaration - usual for "c"
WORD GetFreeSystemResources(WORD type);
//It is console win app
int main( int argc, char *argv[ ], char *envp[ ] )
{
WORD lSysRes = GetFreeSystemResources(GFSR_SYSTEMRESOURCES);
WORD lGdiRes = GetFreeSystemResources(GFSR_GDIRESOURCES);
WORD lUsrRes = GetFreeSystemResources(GFSR_USERRESOURCES);
printf("System resource: %d%%\n", lSysRes);
printf("GDI resource: %d%%\n", lGdiRes);
printf("User resource: %d%%\n", lUsrRes);
return 0;
}
//We need this pragma to make a compiler even don't think about to modify a code in release mode
#pragma optimize ("", off)
WORD GetFreeSystemResources(WORD type)
{
//SAFE macro just returns 99 if something goes wrong (say under NT)
#define DUMMY_RES 99
#define SAFE(a) if(!(a)) return DUMMY_RES
//Decarations "c" style
typedef HINSTANCE (WINAPI* LOADLIB16)(char*);
typedef LONG (WINAPI* GETPROC16)(HINSTANCE, LPCSTR);
typedef BOOL (WINAPI* FREELIB16)(HINSTANCE);
FARPROC QT_Thunk;
LOADLIB16 pLoadLib16;
GETPROC16 pGetProc16;
FREELIB16 pFreeLib16;
HINSTANCE hInst;
DWORD pGetRes;
WORD user_fsr;
WORD _type;
HMODULE hKernel;
//Usuall Windows API calls
SAFE( hKernel = GetModuleHandle("KERNEL32"));
SAFE( QT_Thunk = GetProcAddress(hKernel, "QT_Thunk"));
//Andrew Schulman's
SAFE( pLoadLib16 = (LOADLIB16) GetK32ProcAddress(LOADLIBRARY16_ORD));
SAFE( pGetProc16 = (GETPROC16) GetK32ProcAddress(GETPROCADDRESS16_ORD));
SAFE( pFreeLib16 = (FREELIB16) GetK32ProcAddress(FREELIBRARY16_ORD));
//Usuall for "c"-style calls - by pointer to function
SAFE( hInst = (*pLoadLib16)("user"));
(*pFreeLib16)(hInst);
SAFE( pGetRes = (*pGetProc16)(hInst,"GetFreeSystemResources"));
//How to call 16-bit dll API from 32-bit .exe using QT_Thunk function
/*Actually it is
__asm mov edx, *pGetRes
return (*QT_Thunk)(type);
but compiler may produce a differnt code.
To make QT_Thunk work we need exact code bellow
*/
_type = type;//for inline asm only
if (pGetRes)
_asm
{
push _type
mov edx, [pGetRes]
call QT_Thunk
mov [user_fsr], ax
}
return user_fsr;
/*There is another approach in MSVC documentation - "Thunk Compiler" chapter.
I tried to learn about "Thunk Compiler" several times and finally understood nothing.*/
#undef DUMMY_RES
#undef SAFE
}
#pragma optimize ("", on)
[这就是前面提到的引用的代码]
[头文件]
/*
K32EXP.H -- Get32ProcAddress
Win32 code to import by ordinal from KERNEL32.DLL in Windows 95
See K32EXP.C for more information
*/
// KERNEL32.1 through KERNEL32.9 are all VxDCall
#define VXDCALL_ORD 1
// found these by examining RUNDLL32.EXE
#define LOADLIBRARY16_ORD 35
#define FREELIBRARY16_ORD 36
#define GETPROCADDRESS16_ORD 37
// found these by examining WOW32.DLL
// actually, these are documented: see GENTHUNK.TXT ("Windows NT
// Generic Thunk Overview") and WOWNT32.H in Microsoft's Win32 SDK
#define WOWCallback16_ORD 54
#define WOWCallback16Ex_ORD 55
#define WOWGetVDMPointer_ORD 56
#define WOWHandle32_ORD 57
#define WOWHandle16_ORD 58
#define WOWGlobalAlloc16_ORD 59
#define WOWGlobalLock16_ORD 60
#define WOWGlobalUnlock16_ORD 61
#define WOWGlobalFree16_ORD 62
#define WOWGlobalAllocLock16_ORD 63
#define WOWGlobalUnlockFree16_ORD 64
#define WOWGlobalLockSize16_ORD 65
#define WOWYield16_ORD 66
#define WOWDirectedYield16_ORD 67
#define WOWGetVDMPointerFix_ORD 68
#define WOWGetVDMPointerUnfix_ORD 69
#define WOW32_1_ORD 70
// found these by examining NTDLL.DLL (Win95)
#define RtlLargeIntegerAdd_ORD 72
#define RtlEnlargedIntegerMultiply_ORD 73
#define RtlEnlargedUnsignedMultiply_ORD 74
#define RtlEnlargedUnsignedDivide_ORD 75
#define RtlExtendedLargeIntegerDivide_ORD 76
#define RtlExtendedMagicDivide_ORD 77
#define RtlExtendedIntegerMultiply_ORD 78
#define RtlLargeIntegerShiftLeft_ORD 79
#define RtlLargeIntegerShiftRight_ORD 80
#define RtlLargeIntegerArithmeticShift_ORD 81
#define RtlLargeIntegerNegate_ORD 82
#define RtlLargeIntegerSubtract_ORD 83
#define RtlConvertLongToLargeInteger_ORD 84
#define RtlConvertUlongToLargeInteger_ORD 85
#define GETPWIN16LOCK_ORD 93
#define ENTERSYSLEVEL_ORD 97
#define LEAVESYSLEVEL_ORD 98
DWORD WINAPI GetK32ProcAddress(int ord);
// VxDCall is probably the most important undocumented Win32 API
DWORD (WINAPI *VxDCall)(DWORD srvc, DWORD eax, DWORD ecx);
// Walking VxD chain shows that these are the VxDs that provide
// Win32 services
#define VMM_ID 0x0001 // 41 services
#define REBOOT_ID 0x0009 // 2
#define VNETBIOS_ID 0x0014 // 2
#define VWIN3
[实现部分]
/*
K32EXP.C -- Get32ProcAddress
Win32 code to import by ordinal from KERNEL32.DLL in Windows 95
After Andrew Schulman wrote Unauthorized Windows 95 (IDG Books, 1994), KERNEL32.DLL
stopped exporting undocumented Win32 functions such as VxDCall() and
GetpWin16Lock() by name. The functions discussed in *Unauthorized*
continue to be exported by ordinal (for example, VxDCall is
KERNEL32.1 and GetpWin16Lock is KERNEL.93). However, KERNEL32 does
not allow imports by ordinal (Message from debug version:
"GetProcAddress: kernel32 by id not supported").
This module provides GetK32ProcAddress() to support import by ordinal
from KERNEL32. There's nothing undocumented in here, except for the
ordinal numbers themselves. GetModuleHandle() returns the address of
the executable image (see Matt Pietrek in *Microsoft Systems Journal*,
September 1995, p. 20), and the image is documented in the PE (Portable
Executable) file format.
*/
#include <windows.h>
#include "k32exp.h"
#define ENEWHDR 0x003CL /* offset of new EXE header */
#define EMAGIC 0x5A4D /* old EXE magic id: 'MZ' */
#define PEMAGIC 0x4550 /* NT portable executable */
#define GET_DIR(x) (hdr->OptionalHeader.DataDirectory[x].VirtualAddress)
DWORD WINAPI GetK32ProcAddress(int ord)
{
static HANDLE hmod = 0;
IMAGE_NT_HEADERS *hdr;
IMAGE_EXPORT_DIRECTORY *exp;
DWORD *AddrFunc;
WORD enewhdr, *pw;
int did_load = 0;
BYTE *moddb;
if (hmod == 0) // one-time static init
hmod = GetModuleHandle("KERNEL32");
if (hmod == 0) // still
return 0;
moddb = (BYTE *) hmod;
pw = (WORD *) &moddb[0];
if (*pw != EMAGIC)
return 0;
pw = (WORD *) &moddb[ENEWHDR];
enewhdr = *pw;
pw = (WORD *) &moddb[enewhdr];
if (*pw != PEMAGIC)
return 0;
hdr = (IMAGE_NT_HEADERS *) pw;
// Note: offset from moddb, *NOT* from hdr!
exp = (IMAGE_EXPORT_DIRECTORY *) (((DWORD) moddb) +
((DWORD) GET_DIR(IMAGE_DIRECTORY_ENTRY_EXPORT)));
AddrFunc = (DWORD *) (moddb + (DWORD) exp->AddressOfFunctions);
// should verify that e.g.:
// GetProcAddress(hmod, "VirtualAlloc") == GetK32ProcAddress(710);
ord--; // table is 0-based, ordinals are 1-based
if (ord < (int) exp->NumberOfFunctions)
return ((DWORD) (moddb + AddrFunc[ord]));
else
return 0;
}
---- ◢█◣◢█◣
◤◥◢█◤◥
◣◢█◤◣◢
◥█◤◥█◤ |
|