简洁有力的纯win32的SSDT List
本帖最后由 diddom 于 2012-5-23 01:45 编辑很棒的入门款式
纯win32的唷,有ListView且双色item
Hook地方还用红色字标示
// SystemTool.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include <stdio.h>
#include <windows.h>
#include <winnt.h>
#include <WindowsX.h>
#include <commctrl.h>
#pragma comment(lib,"comctl32")
typedef ULONG NTSTATUS;
#define MAX_LOADSTRING 100
#define SystemModuleInformation 11
#define ibaseDD *(PDWORD)&ibase
HINSTANCE g_hInst;
HWND hWinMain;
HWND hList;
#define ID_LISTVIEW 1001
#define RVATOVA(base,offset) ((PVOID)((DWORD)(base)+(DWORD)(offset)))
#define ibaseDD *(PDWORD)&ibase
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
typedef struct
{
WORD offset:12;
WORD type:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
typedef
ULONG
(WINAPI *ZWQUERYSYSTEMINFORMATION)
(
DWORD SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
typedef enum _SYSDBG_COMMAND {
SysDbgReadVirtualMemory = 8,
SysDbgWriteVirtualMemory = 9,
} SYSDBG_COMMAND, *PSYSDBG_COMMAND;
typedef struct _MEMORY_CHUNKS
{
ULONG Address;
PVOID Data;
ULONG Length;
} MEMORY_CHUNKS, *PMEMORY_CHUNKS;
typedef
NTSTATUS
(NTAPI * ZWSYSTEMDEBUGCONTROL)
(
SYSDBG_COMMAND ControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength,
PULONG ReturnLength
);
ZWSYSTEMDEBUGCONTROL ZwSystemDebugControl = NULL;
typedef struct _SYSTEM_MODULE_INFORMATION { //Information Class 11
ULONG Reserved;
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName;
} SYSTEM_MODULE_INFORMATION,*PSYSTEM_MODULE_INFORMATION;
typedef struct
{
CHAR fname;
ULONG address1;
ULONG address2;
} SSDT_LIST_ENTRY;
SSDT_LIST_ENTRY ssdt_list;
//ssdt_list = new SSDT_LIST_ENTRY;
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle; // The title bar text
TCHAR szWindowClass; // The title bar text
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
BOOL LocateNtdllEntry();
BOOL DebugPrivilege(TCHAR *PName,BOOL bEnable);
void InitListView();
void GetSSDT();
void FindExport();
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_SYSTEMTOOL, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SYSTEMTOOL);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
//delete [] ssdt_list;
return msg.wParam;
}
//
//FUNCTION: MyRegisterClass()
//
//PURPOSE: Registers the window class.
//
//COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SYSTEMTOOL);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCSTR)IDC_SYSTEMTOOL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
hWinMain = hWnd;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
//FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//PURPOSE:Processes messages for the main window.
//
//WM_COMMAND - process the application menu
//WM_PAINT - Paint the main window
//WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello;
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_NOTIFY:
switch (LOWORD(wParam))
{
case ID_LISTVIEW:
//LPNMHDR pnm = (LPNMHDR)lParam;
//if(pnm->hwndFrom != m_hWnd)
//SendMessage(pnm->hwndFrom,msg,wParam,lParam);
//LPNMHDR pnm = (LPNMHDR) lParam;
//if(pnm->code == NM_CUSTOMDRAW)
if(((LPNMHDR)lParam)->code == NM_CUSTOMDRAW)
{
//LPNMLVCUSTOMDRAW lpLVCD = (LPNMLVCUSTOMDRAW) lParam;
//switch(lpLVCD->nmcd.dwDrawStage)
switch(((LPNMLVCUSTOMDRAW)lParam)->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
{ //設置不同顏色
LPNMLVCUSTOMDRAW customDraw = (LPNMLVCUSTOMDRAW) lParam;
customDraw->clrTextBk=customDraw->nmcd.dwItemSpec%2?RGB(250, 250, 250):RGB(0xFF, 0xFF, 0xFF);
if (ssdt_list.address1 != ssdt_list.address2) customDraw->clrText = RGB(255, 0, 0) ;
else customDraw->clrText = RGB(0, 0, 0) ;
return CDRF_NEWFONT;
}
break;
default:
return CDRF_DODEFAULT;
}
}
if(((LPNMHDR)lParam)->code == WM_ERASEBKGND)
{
int ii;
ii = 0;
}
break;
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_ERASEBKGND:
//return TRUE;
break;
case WM_SIZE:
MoveWindow(hList, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_CREATE:
hWinMain = hWnd;
InitListView();
LocateNtdllEntry();
FindExport();
DebugPrivilege(SE_DEBUG_NAME,TRUE);
GetSSDT();
return 0;
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);
DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
//
//
BOOL LocateNtdllEntry()
{
HMODULE ntdll_dll = NULL;
if (!(ntdll_dll = GetModuleHandle("ntdll.dll"))) return FALSE;
if (!( ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(ntdll_dll, "ZwQuerySystemInformation" )))
return FALSE;
if (!( ZwSystemDebugControl = (ZWSYSTEMDEBUGCONTROL)GetProcAddress(ntdll_dll, "ZwSystemDebugControl" )))
return FALSE;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
//
//
BOOL DebugPrivilege(TCHAR *PName,BOOL bEnable)
{
BOOL fOk = FALSE;
HANDLE hToken;
TOKEN_PRIVILEGEStp;
if(OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,&hToken))
{
tp.PrivilegeCount = 1;
tp.Privileges.Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
LookupPrivilegeValue(NULL,PName,&tp.Privileges.Luid);
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL);
fOk=(GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return fOk;
}
//////////////////////////////////////////////////////////////////////////
//
//
DWORD GetHeaders(PCHAR ibase,
PIMAGE_FILE_HEADER *pfh,
PIMAGE_OPTIONAL_HEADER *poh,
PIMAGE_SECTION_HEADER *psh)
{
PIMAGE_DOS_HEADER mzhead = (PIMAGE_DOS_HEADER)ibase;
if ((mzhead->e_magic != IMAGE_DOS_SIGNATURE) || (ibaseDD != IMAGE_NT_SIGNATURE))
return FALSE;
*pfh = (PIMAGE_FILE_HEADER)&ibase;
if (((PIMAGE_NT_HEADERS)*pfh)->Signature != IMAGE_NT_SIGNATURE)
return FALSE;
*pfh = (PIMAGE_FILE_HEADER)((PBYTE)*pfh + sizeof(IMAGE_NT_SIGNATURE));
*poh = (PIMAGE_OPTIONAL_HEADER)((PBYTE)*pfh + sizeof(IMAGE_FILE_HEADER));
if ((*poh)->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
return FALSE;
*psh = (PIMAGE_SECTION_HEADER)((PBYTE)*poh + sizeof(IMAGE_OPTIONAL_HEADER));
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
//
//
void FindExport()
{
PIMAGE_FILE_HEADER pfh;
PIMAGE_OPTIONAL_HEADER poh;
PIMAGE_SECTION_HEADER psh;
PIMAGE_EXPORT_DIRECTORY ped;
DWORD* arrayOfFunctionNames;
DWORD* arrayOfFunctionAddresses;
WORD* arrayOfFunctionOrdinals;
DWORD functionOrdinal;
DWORD functionAddress;
HMODULE hNtdll = GetModuleHandle(TEXT("ntdll.dll"));
GetHeaders((PCHAR)hNtdll, &pfh, &poh, &psh);
if (poh->DataDirectory.VirtualAddress)
{
ped = (PIMAGE_EXPORT_DIRECTORY)(poh->DataDirectory.VirtualAddress + (BYTE*)hNtdll);
arrayOfFunctionNames = (DWORD*)(ped->AddressOfNames + (BYTE*)hNtdll);
arrayOfFunctionAddresses = (DWORD*)((BYTE*)hNtdll + ped->AddressOfFunctions);
arrayOfFunctionNames = (DWORD*)((BYTE*)hNtdll + ped->AddressOfNames);
arrayOfFunctionOrdinals = (WORD*)((BYTE*)hNtdll + ped->AddressOfNameOrdinals);
for (int i=0; i < ped->NumberOfNames; i++)
{
char* fun_name = (char*)((BYTE*)hNtdll + arrayOfFunctionNames);
functionOrdinal = arrayOfFunctionOrdinals + ped->Base - 1;
functionAddress = (DWORD)((BYTE*)hNtdll + arrayOfFunctionAddresses);
if (fun_name == 'N' && fun_name == 't')
{
WORD number = *((WORD*)(functionAddress + 1));
if (number>ped->NumberOfNames) continue;
lstrcpy(ssdt_list.fname, fun_name);
}
}
}
}
//////////////////////////////////////////////////////////////////////////
//
//
DWORD FindKiServiceTable(HMODULE hModule, DWORD dwKSDT)
{
PIMAGE_FILE_HEADER pfh;
PIMAGE_OPTIONAL_HEADER poh;
PIMAGE_SECTION_HEADER psh;
PIMAGE_BASE_RELOCATION pbr;
PIMAGE_FIXUP_ENTRY pfe;
DWORD dwFixups = 0, i, dwPointerRva, dwPointsToRva, dwKiServiceTable;
BOOL bFirstChunk;
GetHeaders((PCHAR)hModule, &pfh, &poh, &psh);
// loop thru relocs to speed up the search
if ((poh->DataDirectory.VirtualAddress) &&
(!((pfh->Characteristics)&IMAGE_FILE_RELOCS_STRIPPED)))
{
pbr = (PIMAGE_BASE_RELOCATION) RVATOVA(poh->DataDirectory.VirtualAddress, hModule);
bFirstChunk = TRUE;
// 1st IMAGE_BASE_RELOCATION.VirtualAddress of ntoskrnl is 0
while (bFirstChunk || pbr->VirtualAddress)
{
bFirstChunk = FALSE;
pfe=(PIMAGE_FIXUP_ENTRY)((DWORD)pbr+sizeof(IMAGE_BASE_RELOCATION));
for (i=0; i < (pbr->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) >> 1; i++, pfe++)
{
if (pfe->type == IMAGE_REL_BASED_HIGHLOW)
{
dwFixups++;
dwPointerRva = pbr->VirtualAddress + pfe->offset;
// DONT_RESOLVE_DLL_REFERENCES flag means relocs aren't fixed
dwPointsToRva = *(PDWORD)((DWORD)hModule+dwPointerRva)-(DWORD)poh->ImageBase;
// does this reloc point to KeServiceDescriptorTable.Base?
if (dwPointsToRva == dwKSDT)
{
// check for mov ,imm32. we are trying to find
// "mov ds:_KeServiceDescriptorTable.Base, offset _KiServiceTable"
// from the KiInitSystem.
if (*(PWORD)((DWORD)hModule + dwPointerRva-2) == 0x05c7)
{
// should check for a reloc presence on KiServiceTable here
// but forget it
dwKiServiceTable = *(PDWORD)((DWORD)hModule + dwPointerRva + 4) - poh->ImageBase;
return dwKiServiceTable;
}
}
}
// should never get here
}
*(PDWORD)&pbr += pbr->SizeOfBlock;
}
}
return 0;
}
DWORD dwKSDT; // rva of KeServiceDescriptorTable
DWORD dwKiServiceTable; // rva of KiServiceTable
DWORD dwKernelBase, dwServices = 0;
//////////////////////////////////////////////////////////////////////////
//
//
void GetSSDT()
{
HMODULE hKernel;
PCHAR pKernelName;
PDWORD pService;
PIMAGE_FILE_HEADER pfh;
PIMAGE_OPTIONAL_HEADERpoh;
PIMAGE_SECTION_HEADER psh;
ULONG n;
// get system modules - ntoskrnl is always first there
ZwQuerySystemInformation(SystemModuleInformation, &n, 0, &n);
PULONG p = new ULONG;
ZwQuerySystemInformation(SystemModuleInformation, p, n * sizeof(*p), 0);
PSYSTEM_MODULE_INFORMATION module = PSYSTEM_MODULE_INFORMATION(p+1);
// imagebase
dwKernelBase = (DWORD)module->Base;
USHORT ofs = module->ModuleNameOffset;
char* imgName = (char*)module->ImageName;
pKernelName = ofs + imgName;
// filename - it may be renamed in the boot.ini
pKernelName = module->ModuleNameOffset + module->ImageName;
// map ntoskrnl - hopefully it has relocs
hKernel = LoadLibraryEx(pKernelName, 0, DONT_RESOLVE_DLL_REFERENCES);
if(!hKernel) {
return;
}
// our own export walker is useless here - we have GetProcAddress :)
if (!(dwKSDT = (DWORD)GetProcAddress(hKernel, "KeServiceDescriptorTable"))) {
return;
}
// get KeServiceDescriptorTable rva
dwKSDT -= (DWORD)hKernel;
// find KiServiceTable
if (!(dwKiServiceTable = FindKiServiceTable(hKernel, dwKSDT))) {
return;
}
// let's dump KiServiceTable contents
// MAY FAIL!!!
// should get right ServiceLimit here, but this is trivial in the kernel mode
GetHeaders((PCHAR)hKernel, &pfh, &poh, &psh);
dwServices = 0;
for (pService = (PDWORD)((DWORD)hKernel+dwKiServiceTable);
*pService - poh->ImageBase < poh->SizeOfImage;
pService++, dwServices++)
{
ssdt_list.address1 = *pService - poh->ImageBase + dwKernelBase;
}
FreeLibrary(hKernel);
MEMORY_CHUNKS QueryBuff;
DWORD *address2 = new DWORD;
QueryBuff.Address = dwKernelBase+dwKiServiceTable;
QueryBuff.Data = address2;
QueryBuff.Length = sizeof(DWORD)*dwServices;
DWORD ReturnLength;
ZwSystemDebugControl(
SysDbgReadVirtualMemory,
&QueryBuff, sizeof(MEMORY_CHUNKS), NULL,
0, &ReturnLength);
LV_ITEM lvi;
lvi.mask = LVIF_TEXT;
char tmp;
ListView_DeleteAllItems(hList);
for (int j=0; j < dwServices; j++)
{
lvi.iItem = j;
lvi.iSubItem = 0;
lvi.pszText = tmp;
wsprintf(tmp, "0x%02X", j);
ListView_InsertItem(hList, &lvi);
ListView_SetItemText(hList, j, 1, ssdt_list.fname);
wsprintf(tmp, "0x%08X", ssdt_list.address1);
ListView_SetItemText(hList, j, 2, tmp);
wsprintf(tmp,"0x%08X", address2);
ssdt_list.address2 = address2;
ListView_SetItemText(hList, j, 3, tmp);
for(int i=0; i < *p; i++)
{
if (ssdt_list.address2 > (DWORD)module.Base&&ssdt_list.address2 < (DWORD)module.Base+module.Size)
{
ListView_SetItemText(hList, j, 4, module.ImageName);
break;
}
}
}
delete [] p;
delete [] address2;
}
void InitListView()
{
INITCOMMONCONTROLSEX iex;
iex.dwSize = sizeof(iex);
iex.dwICC=ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&iex);
hList = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, NULL,
WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHAREIMAGELISTS,
0, 0, 0, 0, hWinMain, (HMENU)ID_LISTVIEW, g_hInst, NULL);
SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES);
LV_COLUMN lvc;
lvc.mask = LVCF_TEXT | LVCF_WIDTH ;
lvc.fmt = LVCFMT_RIGHT;
lvc.pszText = "No.";
lvc.cx = 50;
SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&lvc);
lvc.mask |= LVCF_FMT;
lvc.fmt = LVCFMT_LEFT;
lvc.pszText = "Function Name";
lvc.cx = 350;
SendMessage(hList, LVM_INSERTCOLUMN, 1, (LPARAM)&lvc);
lvc.pszText = "OrgAddr";
lvc.cx = 100;
SendMessage(hList, LVM_INSERTCOLUMN, 2, (LPARAM)&lvc);
lvc.pszText = "HookAddr";
lvc.cx = 100;
SendMessage(hList, LVM_INSERTCOLUMN, 3, (LPARAM)&lvc);
lvc.pszText = "Module";
lvc.cx = 200;
SendMessage(hList, LVM_INSERTCOLUMN, 4, (LPARAM)&lvc);
}
页:
[1]