├── src ├── windows │ ├── drv │ │ ├── dirs │ │ ├── sys │ │ │ ├── sources │ │ │ ├── kb.rc │ │ │ ├── makefile │ │ │ ├── kb.h │ │ │ └── kb.c │ │ ├── exe │ │ │ ├── drvctl.h │ │ │ ├── makefile │ │ │ ├── sources │ │ │ ├── test.c │ │ │ └── drvctl.c │ │ └── run.bat │ ├── exploits │ │ ├── mplayer.zip │ │ ├── reader.zip │ │ └── exploits.txt │ ├── detour │ │ ├── run_mplayer.bat │ │ ├── run_acrord.bat │ │ ├── Makefile │ │ └── kb.cpp │ ├── tools │ │ ├── makefile │ │ ├── perf.c │ │ ├── proxify.c │ │ ├── time.c │ │ ├── ps.c │ │ └── loader.c │ └── compile.bat ├── pintool │ ├── makefile │ ├── makefile.lin │ └── btr.cpp ├── tools │ ├── Makefile │ ├── Makefile.lin │ └── anal.c └── common │ ├── decode.h │ └── decode.c ├── bin ├── kb.dll ├── kb.sys ├── test.exe ├── withdll.exe └── run.bat ├── demo.docx ├── report.pdf ├── sec13-paper_pappas.pdf ├── README.txt └── LICENSE /src/windows/drv/dirs: -------------------------------------------------------------------------------- 1 | DIRS= \ 2 | exe \ 3 | sys -------------------------------------------------------------------------------- /bin/kb.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/bin/kb.dll -------------------------------------------------------------------------------- /bin/kb.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/bin/kb.sys -------------------------------------------------------------------------------- /demo.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/demo.docx -------------------------------------------------------------------------------- /report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/report.pdf -------------------------------------------------------------------------------- /bin/test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/bin/test.exe -------------------------------------------------------------------------------- /bin/withdll.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/bin/withdll.exe -------------------------------------------------------------------------------- /sec13-paper_pappas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/sec13-paper_pappas.pdf -------------------------------------------------------------------------------- /src/windows/exploits/mplayer.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/src/windows/exploits/mplayer.zip -------------------------------------------------------------------------------- /src/windows/exploits/reader.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vpappas/kbouncer/HEAD/src/windows/exploits/reader.zip -------------------------------------------------------------------------------- /src/windows/detour/run_mplayer.bat: -------------------------------------------------------------------------------- 1 | root\bin.X86\withdll.exe /d:root\bin.X86\kb.dll "C:\Users\vpappas\Desktop\mplayer\mplayer.exe" 2 | -------------------------------------------------------------------------------- /src/windows/detour/run_acrord.bat: -------------------------------------------------------------------------------- 1 | root\bin.X86\withdll.exe /d:root\bin.X86\kb.dll "C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32.exe" 2 | -------------------------------------------------------------------------------- /src/pintool/makefile: -------------------------------------------------------------------------------- 1 | PIN_HOME=C:\pin\source\tools 2 | 3 | COMMON_TOOLS=btr.dll 4 | 5 | INCLUDE_SUB_RULES=1 6 | SET_VCENV=0 7 | !INCLUDE $(PIN_HOME)\Nmakefile 8 | -------------------------------------------------------------------------------- /src/windows/drv/sys/sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=kb 2 | TARGETTYPE=DRIVER 3 | 4 | 5 | MSC_WARNING_LEVEL=/W4 /WX 6 | 7 | 8 | SOURCES=kb.c kb.rc 9 | 10 | -------------------------------------------------------------------------------- /src/tools/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = /I..\common 2 | 3 | anal.exe: anal.c ..\common\decode.c 4 | $(CC) $(CFLAGS) /Fe$@ $** 5 | 6 | clean: 7 | del /Q *.obj anal.exe 8 | -------------------------------------------------------------------------------- /src/tools/Makefile.lin: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -I../common 3 | TARGETS = anal 4 | 5 | all: $(TARGETS) 6 | 7 | anal: anal.c ../common/decode.c 8 | $(CC) $(CFLAGS) $^ -o $@ 9 | 10 | clean: 11 | rm -rf $(TARGETS) 12 | -------------------------------------------------------------------------------- /src/windows/drv/exe/drvctl.h: -------------------------------------------------------------------------------- 1 | #ifndef __KB_DRVCTL_H__ 2 | #define __KB_DRVCTL_H__ 3 | 4 | BOOL DriverInit(); 5 | BOOL DriverFini(); 6 | BOOL EnableLBR(); 7 | BOOL DisableLBR(); 8 | BOOL CheckLBR(); 9 | BOOL CheckLBRDump(); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/common/decode.h: -------------------------------------------------------------------------------- 1 | #ifndef __KB_DECODE_H__ 2 | #define __KB_DECODE_H__ 3 | 4 | #define MAX_INSN 16 //bytes in x86 5 | 6 | int decode_ret(unsigned char *insn); 7 | 8 | int decode_call(unsigned char *insn); 9 | 10 | int check_branch(unsigned char *from, unsigned char *to); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/windows/drv/sys/kb.rc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #define VER_FILETYPE VFT_DRV 6 | #define VER_FILESUBTYPE VFT2_DRV_SYSTEM 7 | #define VER_FILEDESCRIPTION_STR "kBouncer Driver" 8 | #define VER_INTERNALNAME_STR "KB.sys" 9 | 10 | #include "common.ver" 11 | 12 | -------------------------------------------------------------------------------- /src/windows/drv/exe/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the driver components of the Windows NT DDK 5 | # 6 | 7 | !INCLUDE $(NTMAKEENV)\makefile.def 8 | 9 | -------------------------------------------------------------------------------- /src/windows/drv/sys/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the driver components of the Windows NT DDK 5 | # 6 | 7 | !INCLUDE $(NTMAKEENV)\makefile.def 8 | 9 | -------------------------------------------------------------------------------- /src/windows/tools/makefile: -------------------------------------------------------------------------------- 1 | TARGETS = ps.exe proxify.exe loader.exe perf.exe time.exe 2 | CFLAGS = /nologo 3 | 4 | all: $(TARGETS) 5 | 6 | .SUFFIXES: .c .exe 7 | 8 | .c.exe: 9 | $(CC) $(CFLAGS) $< 10 | 11 | perf.exe: perf.c ..\drv\exe\drvctl.c 12 | $(CC) $(CFLAGS) /Ox $** 13 | 14 | clean: 15 | del /Q $(TARGETS) *.obj 16 | -------------------------------------------------------------------------------- /src/pintool/makefile.lin: -------------------------------------------------------------------------------- 1 | CXX := g++ 2 | TOOL := btr.so 3 | 4 | PIN_KIT=/home/vpappas/pin/pin-2.10-45467-gcc.3.4.6-ia32_intel64-linux 5 | 6 | include $(PIN_KIT)/source/tools/makefile.gnu.config 7 | 8 | all: $(TOOL) 9 | 10 | %.so: %.cpp 11 | $(CXX) $(CXXFLAGS) $(PIN_CXXFLAGS) $(PIN_LDFLAGS) -o $@ $< $(PIN_LIBS) 12 | 13 | clean: 14 | rm -f $(TARGET) 15 | -------------------------------------------------------------------------------- /src/windows/drv/exe/sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=test 2 | TARGETTYPE=PROGRAM 3 | MSC_WARNING_LEVEL=/W4 /WX 4 | C_DEFINES=/DSTANDALONE 5 | MSC_OPTIMIZATION=/Od 6 | SOURCES=drvctl.c test.c 7 | TARGETLIBS=$(SDK_LIB_PATH)\user32.lib 8 | 9 | 10 | UMTYPE=console 11 | UMBASE=0x04000000 12 | 13 | USE_MSVCRT=1 14 | 15 | _NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP) 16 | 17 | -------------------------------------------------------------------------------- /src/windows/exploits/exploits.txt: -------------------------------------------------------------------------------- 1 | ## CVE-2010-2883 - Adobe CoolType SING Table "uniqueName" Stack Buffer Overflow (reader3) 2 | Reader <= 9.3.4 3 | metasploit: windows/fileformat/adobe_cooltype_sing 4 | http://www.exploit-db.com/exploits/16619/ 5 | http://www.vupen.com/blog/20100909.Adobe_Acrobat_Reader_0_Day_Exploit_CVE-2010-2883_Technical_Analysis.php 6 | ROP from icucnv36.dll 7 | 8 | ## Mplayer Lite r33064 9 | http://www.exploit-db.com/exploits/17124/ 10 | 11 | 12 | note: zip password is 'infected' without quotes 13 | -------------------------------------------------------------------------------- /bin/run.bat: -------------------------------------------------------------------------------- 1 | @echo OFF 2 | 3 | set drv=%~dp0\kb.sys 4 | 5 | if not exist %drv% set drv=%~dp0\sys\objfre_win7_amd64\amd64\kb.sys 6 | 7 | echo using driver %drv% 8 | 9 | echo creating the kb service 10 | sc.exe create kb type= kernel binpath= %drv% 11 | if %errorlevel% neq 0 exit /b %errorlevel% 12 | 13 | echo starting the kb service 14 | sc.exe start kb 15 | if %errorlevel% neq 0 exit /b %errorlevel% 16 | 17 | echo press enter to stop 18 | pause 19 | 20 | echo stopping the kb service 21 | sc.exe stop kb 22 | if %errorlevel% neq 0 exit /b %errorlevel% 23 | 24 | echo deleting the kb service 25 | sc.exe delete kb 26 | if %errorlevel% neq 0 exit /b %errorlevel% 27 | -------------------------------------------------------------------------------- /src/windows/drv/run.bat: -------------------------------------------------------------------------------- 1 | @echo OFF 2 | 3 | set drv=%~dp0\kb.sys 4 | 5 | if not exist %drv% set drv=%~dp0\sys\objfre_win7_amd64\amd64\kb.sys 6 | 7 | echo using driver %drv% 8 | 9 | echo creating the kb service 10 | sc.exe create kb type= kernel binpath= %drv% 11 | if %errorlevel% neq 0 exit /b %errorlevel% 12 | 13 | echo starting the kb service 14 | sc.exe start kb 15 | if %errorlevel% neq 0 exit /b %errorlevel% 16 | 17 | echo press enter to stop 18 | pause 19 | 20 | echo stopping the kb service 21 | sc.exe stop kb 22 | if %errorlevel% neq 0 exit /b %errorlevel% 23 | 24 | echo deleting the kb service 25 | sc.exe delete kb 26 | if %errorlevel% neq 0 exit /b %errorlevel% 27 | -------------------------------------------------------------------------------- /src/windows/drv/sys/kb.h: -------------------------------------------------------------------------------- 1 | // 2 | // Device type -- in the "User Defined" range." 3 | // 4 | #define KB_TYPE 60000 5 | 6 | // 7 | // The IOCTL function codes from 0x800 to 0xFFF are for customer use. 8 | // 9 | #define IOCTL_KB_ENABLE_LBR \ 10 | CTL_CODE( KB_TYPE, 0x900, METHOD_NEITHER, FILE_ANY_ACCESS ) 11 | 12 | #define IOCTL_KB_DUMP_LBR \ 13 | CTL_CODE( KB_TYPE, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS ) 14 | 15 | #define IOCTL_KB_CHECK_LBR \ 16 | CTL_CODE( KB_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS ) 17 | 18 | #define IOCTL_KB_DISABLE_LBR \ 19 | CTL_CODE( KB_TYPE, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS ) 20 | 21 | #define DRIVER_FUNC_INSTALL 0x01 22 | #define DRIVER_FUNC_REMOVE 0x02 23 | 24 | #define DRIVER_NAME "kb" 25 | 26 | #define LBR_SZ 16 // Nehalem 27 | 28 | typedef struct { 29 | __int64 from; 30 | __int64 to; 31 | } BR, *PBR; 32 | -------------------------------------------------------------------------------- /src/windows/compile.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set WDK_ROOT=C:\WinDDK\7600.16385.1 4 | set WDK_SETENV=%WDK_ROOT%\bin\setenv.bat %WDK_ROOT% fre x64 WIN7 5 | 6 | set SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows\v7.1 7 | set SDK_SETENV=%SDK_ROOT%\bin\setenv.cmd 8 | 9 | set KB_ROOT=C:\kbouncer 10 | 11 | set OUT_DIR=.\bin 12 | 13 | 14 | echo will put binary files in '%OUT_DIR%' 15 | 16 | :: if exist %OUT_DIR%\nul ( 17 | :: echo %OUT_DIR% already exists! 18 | :: exit /b 19 | :: ) 20 | 21 | mkdir %OUT_DIR% 22 | 23 | echo compiling the driver 24 | 25 | cmd /c "call %WDK_SETENV% & cd %KB_ROOT%\windows\drv & build" 26 | 27 | echo compiling the detour 28 | 29 | cmd /c "call "%SDK_SETENV%" /x86 & cd %KB_ROOT%\windows\detour & nmake" 30 | 31 | echo copying files 32 | 33 | copy %KB_ROOT%\windows\drv\sys\objfre_win7_amd64\amd64\kb.sys %OUT_DIR% 34 | copy %KB_ROOT%\windows\drv\exe\objfre_win7_amd64\amd64\test.exe %OUT_DIR% 35 | copy %KB_ROOT%\windows\drv\run.bat %OUT_DIR% 36 | 37 | copy %KB_ROOT%\windows\detour\root\bin.x86\kb.dll %OUT_DIR% 38 | copy %KB_ROOT%\windows\detour\root\bin.x86\withdll.exe %OUT_DIR% 39 | 40 | copy %KB_ROOT%\windows\exploits\reader\*.pdf %OUT_DIR% 41 | copy %KB_ROOT%\windows\exploits\mplayer\*.m3u %OUT_DIR% 42 | 43 | 44 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | --= Prerequisites =-- 2 | 3 | 1) Microsoft .NET Framework 4 4 | http://www.microsoft.com/download/en/details.aspx?id=17851 5 | 6 | 2) Windows SDK 7.1 7 | http://www.microsoft.com/download/en/details.aspx?id=8279 8 | untick Itanium libraries, .NET development and Common Utilities 9 | 10 | 3) Windows Driver Kit 7.1.0 11 | http://www.microsoft.com/download/en/details.aspx?id=11800 12 | full environment + debugging tools 13 | 14 | 4) Detours Express 3.0 Build_308 15 | http://research.microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default.aspx 16 | install it in the default directory! 17 | 18 | 5) Pin 2.10 VS10 19 | http://www.cs.virginia.edu/kim/publicity/pin/kits/pin-2.10-45467-msvc10-ia32_intel64-windows.zip 20 | 21 | 22 | --= Quick compile =-- 23 | 1) run the compile.bat script in the windows directory 24 | it will produce a bin directory with all the files 25 | 26 | --= Setup =-- 27 | 1) run as adimistrator "bcdedit -debug on" and reboot 28 | 29 | --= Compile the detour =-- 30 | 1) run the sdk build environment as administrator 31 | 2) setenv /x86 32 | 3) nmake 33 | 34 | --= Compile the driver =-- 35 | 1) run the x64 Free build environment 36 | 2) bld /w 37 | 38 | --= Test =-- 39 | 1) disable driver signature enforcement (press F8 while 40 | booting and select the appropriate option) 41 | 2) start a cmd with as administrator 42 | 3) load the driver by executing start run.bat in the drv 43 | dir (ignore warning about signinig) 44 | 4) start the detoured reader by executing run_acrord.bat 45 | in the detour dir 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, Vasilis Pappas 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | * Neither the name of the Columbia University nor the names of its contributors 13 | may be used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /src/windows/tools/perf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "..\drv\exe\drvctl.h" 5 | #include "..\..\common\decode.h" 6 | 7 | #pragma comment(lib, "user32.lib") 8 | 9 | #define LOG(x, ...) fprintf(stderr, x, __VA_ARGS__) 10 | 11 | 12 | DWORD TimeSysCheck(DWORD num) 13 | { 14 | DWORD i; 15 | 16 | if (!DriverInit()) { 17 | LOG("failed to init driver\n"); 18 | return 1; 19 | } 20 | 21 | if (!EnableLBR()) { 22 | LOG("failed to enable LBR\n"); 23 | return 1; 24 | } 25 | 26 | for (i=0; i < num; i++) { 27 | if (!CheckLBR()) { 28 | LOG("failed to check LBR\n"); 29 | return 1; 30 | } 31 | } 32 | 33 | if (!DisableLBR()) { 34 | LOG("failed to disable LBR\n"); 35 | return 1; 36 | } 37 | 38 | if (!DriverFini()) { 39 | LOG("failed to fini driver\n"); 40 | return 1; 41 | } 42 | 43 | return 0; 44 | } 45 | 46 | DWORD TimeUserCheck(DWORD num) 47 | { 48 | MEMORY_BASIC_INFORMATION mi; 49 | PUCHAR base, addr; 50 | SIZE_T size; 51 | DWORD i; 52 | 53 | // VirualQuery is in kernel32.dll 54 | if (VirtualQuery(VirtualQuery, &mi, sizeof(mi)) == 0) { 55 | LOG("failed to vquery %d\n", GetLastError()); 56 | return 1; 57 | } 58 | 59 | base = mi.AllocationBase; 60 | size = mi.RegionSize; 61 | 62 | for (i=0; i < num; i++) { 63 | addr = base + i % size; 64 | check_branch(addr, addr); 65 | } 66 | 67 | return 0; 68 | } 69 | 70 | DWORD main(DWORD argc, CHAR *argv[]) 71 | { 72 | ULARGE_INTEGER start, end; 73 | FILETIME ft; 74 | 75 | GetSystemTimeAsFileTime(&ft); 76 | start.LowPart = ft.dwLowDateTime; 77 | start.HighPart = ft.dwHighDateTime; 78 | 79 | //TimeUserCheck(1000000000); 80 | 81 | TimeSysCheck (10000000); 82 | 83 | GetSystemTimeAsFileTime(&ft); 84 | end.LowPart = ft.dwLowDateTime; 85 | end.HighPart = ft.dwHighDateTime; 86 | 87 | 88 | printf("took %lld ms\n", (end.QuadPart-start.QuadPart)/10000); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /src/windows/tools/proxify.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #pragma comment(lib, "imagehlp.lib") 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | LOADED_IMAGE img; 10 | PIMAGE_EXPORT_DIRECTORY exp; 11 | DWORD *nams, *rvas, exp_size; 12 | WORD *ords; 13 | LPVOID func; 14 | char module[MAX_PATH], *tmp, *name; 15 | int i; 16 | 17 | if (argc != 3) { 18 | fprintf(stderr, "usage: %s image dest\n", argv[0]); 19 | return 1; 20 | } 21 | 22 | if (MapAndLoad(argv[1], NULL, &img, TRUE, TRUE) == FALSE) { 23 | fprintf(stderr, "load failed %d\n", GetLastError()); 24 | return 1; 25 | } 26 | 27 | exp = (PIMAGE_EXPORT_DIRECTORY) ImageRvaToVa( 28 | img.FileHeader, img.MappedAddress, 29 | img.FileHeader->OptionalHeader 30 | .DataDirectory[0].VirtualAddress, 31 | NULL); 32 | 33 | exp_size = img.FileHeader->OptionalHeader.DataDirectory[0].Size; 34 | 35 | rvas = (DWORD*) ImageRvaToVa(img.FileHeader, img.MappedAddress, 36 | exp->AddressOfFunctions, NULL); 37 | 38 | nams = (DWORD*) ImageRvaToVa(img.FileHeader, img.MappedAddress, 39 | exp->AddressOfNames, NULL); 40 | 41 | ords = (WORD*) ImageRvaToVa(img.FileHeader, img.MappedAddress, 42 | exp->AddressOfNameOrdinals, NULL); 43 | 44 | for (i=0; i < exp->NumberOfFunctions; i++) { 45 | 46 | if (i < exp->NumberOfNames) 47 | name = ImageRvaToVa(img.FileHeader, 48 | img.MappedAddress, nams[i], NULL); 49 | else 50 | break; //FIXME: unamed export! 51 | 52 | printf("#pragma comment (linker, \"/export:%s=", name); 53 | 54 | func = ImageRvaToVa(img.FileHeader, 55 | img.MappedAddress, rvas[i], NULL); 56 | 57 | //if (func >= exp && func < (PBYTE)exp + exp_size) //fwd 58 | // printf("%s", func); 59 | //else 60 | printf("%s.%s", argv[2], name); 61 | 62 | printf(",@%d\")\n", ords[i] + exp->Base); 63 | } 64 | 65 | if (UnMapAndLoad(&img) == FALSE) { 66 | fprintf(stderr, "unload failed %d\n", GetLastError()); 67 | return 1; 68 | } 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /src/windows/tools/time.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | DWORD main(DWORD argc, CHAR *argv[]) 6 | { 7 | PROCESS_INFORMATION pi; 8 | STARTUPINFO si; 9 | FILETIME created, exited, sys, user; 10 | ULARGE_INTEGER a, b; 11 | 12 | if (argc != 2) { 13 | printf("usage: %s command\n", argv[0]); 14 | return 1; 15 | } 16 | 17 | // set up members of the PROCESS_INFORMATION structure. 18 | ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 19 | 20 | // set up members of the STARTUPINFO structure. 21 | ZeroMemory(&si, sizeof(STARTUPINFO)); 22 | si.cb = sizeof(STARTUPINFO); 23 | 24 | // create the child process. 25 | if (!CreateProcess(NULL, argv[1], NULL, NULL, TRUE, 26 | 0, NULL, NULL, &si, &pi)) { 27 | printf("CreateProcess failed (%d)\n", GetLastError()); 28 | return 1; 29 | } 30 | 31 | // wait until child process exits. 32 | if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) { 33 | printf("WaitForSingleObject failed (%d)\n", GetLastError()); 34 | return 1; 35 | } 36 | 37 | // get the usage times 38 | if (!GetProcessTimes(pi.hProcess, &created, &exited, &sys, &user)) { 39 | printf("GetProcessTime failed (%d)\n", GetLastError()); 40 | return 1; 41 | } 42 | 43 | // real time (wallclock) 44 | a.LowPart = created.dwLowDateTime; 45 | a.HighPart = created.dwHighDateTime; 46 | b.LowPart = exited.dwLowDateTime; 47 | b.HighPart = exited.dwHighDateTime; 48 | 49 | printf("real %u.%02u\n", (b.QuadPart-a.QuadPart)/10000000, 50 | ((b.QuadPart-a.QuadPart)/100000)%100); 51 | 52 | // user CPU time 53 | a.LowPart = user.dwLowDateTime; 54 | a.HighPart = user.dwHighDateTime; 55 | 56 | printf("user %u.%02u\n", a.QuadPart/10000000, (a.QuadPart/100000)%100); 57 | 58 | // kernel CPU time 59 | a.LowPart = sys.dwLowDateTime; 60 | a.HighPart = sys.dwHighDateTime; 61 | 62 | printf("sys %u.%02u\n", a.QuadPart/10000000, (a.QuadPart/100000)%100); 63 | 64 | CloseHandle(pi.hProcess); 65 | 66 | CloseHandle(pi.hThread); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /src/windows/detour/Makefile: -------------------------------------------------------------------------------- 1 | !IF !EXIST(root) 2 | !IF [mklink /J root \ 3 | "\Program Files (x86)\Microsoft Research\Detours Express 3.0"] != 0 4 | !ERROR "cannot create link!" 5 | !ENDIF 6 | !ENDIF 7 | 8 | ROOT=root 9 | 10 | !include .\root\samples\common.mak 11 | 12 | ############################################################################## 13 | 14 | all: dirs $(BIND)\kb.dll $(BIND)\withdll.exe 15 | 16 | clean: 17 | -del *~ test.txt 2>nul 18 | -del $(BIND)\kb.* 2>nul 19 | -rmdir /q /s $(OBJD) 2>nul 20 | 21 | allclean: clean 22 | cd $(ROOT)\src 23 | nmake clean 24 | cd ..\samples\withdll 25 | nmake clean 26 | cd ..\syelog 27 | nmake clean 28 | 29 | dirs: 30 | if not exist $(BIND) mkdir $(BIND) 31 | if not exist $(OBJD) mkdir $(OBJD) 32 | 33 | realclean: clean 34 | -rmdir /q /s $(OBJDS) 2>nul 35 | 36 | ############################################################################## 37 | 38 | CFLAGS = $(CFLAGS) /I..\drv\exe 39 | 40 | ############################################################################## 41 | 42 | $(INCD)\detours.h : $(LIBD)\detours.lib 43 | 44 | $(LIBD)\detours.lib : 45 | cd $(ROOT)\src 46 | nmake 47 | cd $(MAKEDIR) 48 | 49 | $(BIND)\withdll.exe : $(LIBD)\syelog.lib 50 | cd $(ROOT)\samples\withdll 51 | nmake 52 | cd $(MAKEDIR) 53 | 54 | $(LIBD)\syelog.lib: 55 | cd $(ROOT)\samples\syelog 56 | nmake 57 | cd $(MAKEDIR) 58 | 59 | ############################################################################## 60 | 61 | $(OBJD)\kb.obj : kb.cpp $(INCD)\detours.h 62 | 63 | $(OBJD)\drvctl.obj : ..\drv\exe\drvctl.c 64 | cl.exe /c /DDETOUR /Fo$@ $** 65 | 66 | $(BIND)\kb.dll : $(OBJD)\kb.obj $(LIBD)\detours.lib $(OBJD)\drvctl.obj 67 | cl /LD $(CFLAGS) /Fe$@ /Fd$(BIND)\kb.pdb \ 68 | $(OBJD)\kb.obj $(OBJD)\drvctl.obj \ 69 | /link $(LINKFLAGS) /incremental:no /subsystem:console \ 70 | /entry:$(DLLENTRY) /export:NullExport \ 71 | $(LIBD)\detours.lib user32.lib 72 | 73 | ################################################################# End of File. 74 | 75 | -------------------------------------------------------------------------------- /src/windows/drv/exe/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "drvctl.h" 5 | 6 | #define LOG(x, ...) fprintf(stderr, x, __VA_ARGS__) 7 | 8 | __declspec(noinline) 9 | VOID RopFunc() 10 | { 11 | void *ret = _AddressOfReturnAddress(); 12 | char *val = *(char**) ret; 13 | 14 | *(void**)ret = val + 11; // skips the increment 15 | } 16 | 17 | struct { 18 | int model; 19 | char *name; 20 | } models[] = { 21 | {0x206E6, "Nehalem - Beckton"}, 22 | {0x106A4, "Nehalem - Bloomfield or Gainestown"}, 23 | {0x106A5, "Nehalem - Bloomfield or Gainestown"}, 24 | {0x106E4, "Nehalem - Clarksfield or Lynnfield or Jasper Forest"}, 25 | {0x106E5, "Nehalem - Clarksfield or Lynnfield or Jasper Forest"}, 26 | {0x206F2, "Nehalem - Westmere-EX"}, 27 | {0x206C2, "Nehalem - Gulftown or Westmere-EP"}, 28 | {0x20652, "Nehalem - Arrandale or Clarkdale"}, 29 | {0x20655, "Nehalem - Arrandale or Clarkdale"}, 30 | {0x206A7, "Sandy Bridge - HE-4 or H-2 or M-2"}, 31 | {0x206D6, "Sandy Bridge - EP-8 or EP-4"}, 32 | {0x206D7, "Sandy Bridge - EP-8 or EP-4"}, 33 | {0, NULL} 34 | }; 35 | 36 | 37 | DWORD main() 38 | { 39 | int num=69; 40 | int info[4], i; 41 | 42 | // check the CPU's microarchitecture 43 | __cpuid(info, 1); 44 | 45 | for (i=0; models[i].model != 0 && info[0] != models[i].model; i++) 46 | ; 47 | if (models[i].model != 0) 48 | LOG("CPU: '%s' should support selective LBR\n", models[i].name); 49 | else 50 | LOG("could not identify the CPU model (%x) .. not sure if" 51 | "it supports the selective LBR feature\n", info[0]); 52 | 53 | if (!DriverInit()) { 54 | LOG("failed to init driver\n"); 55 | return 1; 56 | } 57 | 58 | if (!EnableLBR()) { 59 | LOG("failed to enable LBR\n"); 60 | return 1; 61 | } 62 | 63 | RopFunc(); 64 | num++; 65 | 66 | if (!CheckLBR()) { 67 | LOG("failed to check LBR\n"); 68 | return 1; 69 | } 70 | 71 | LOG("num is %d\n", num); 72 | 73 | if (!DisableLBR()) { 74 | LOG("failed to disable LBR\n"); 75 | return 1; 76 | } 77 | 78 | if (!DriverFini()) { 79 | LOG("failed to fini driver\n"); 80 | return 1; 81 | } 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /src/common/decode.c: -------------------------------------------------------------------------------- 1 | #include "decode.h" 2 | 3 | /* 4 | * decode a return instruction, optionally prefixed by rep. 5 | * return the length of the instruction, or 0 if no ret can 6 | * be decoded. 7 | */ 8 | int decode_ret(unsigned char *insn) 9 | { 10 | unsigned int idx=0, ilen=0; 11 | 12 | //skip rep prefix 13 | if (insn[idx] == 0xf3) 14 | idx++; 15 | 16 | switch (insn[idx]) { 17 | case 0xc3: // near ret 18 | case 0xcb: // far ret 19 | ilen = idx + 1; 20 | break; 21 | case 0xc2: // near ret imm16 22 | case 0xca: // far ret imm16 23 | ilen = idx + 1 + 2; 24 | break; 25 | } 26 | 27 | return ilen; 28 | } 29 | 30 | 31 | /* 32 | * decode a call instruction, optionally prefixed. 33 | * return the length of the instruction, or 0 if no 34 | * call can be decoded. 35 | */ 36 | int decode_call(unsigned char *insn) 37 | { 38 | unsigned char word, reg, rm, mod, base; 39 | unsigned int idx=0, ilen=0; 40 | 41 | // parse prefix 42 | 43 | word = 4; // or 2 if in 16-bit mode 44 | 45 | switch (insn[idx]) { 46 | 47 | /* call near relative */ 48 | case 0xe8: 49 | // rel16/32 (16/32/64-bit) 50 | ilen = idx + 1 + word; 51 | break; 52 | 53 | /* reg == 2 -> call near absolute indirect r/m16/32/64 54 | * reg == 3 -> call far absolute indirect m16:16/32/64 */ 55 | case 0xff: 56 | idx++; //there's a modrm byte 57 | reg = (insn[idx] >> 3) & 0x7; //opcode extension 58 | rm = insn[idx] & 0x7; 59 | mod = insn[idx] >> 6; 60 | 61 | // disp16 (special case in 16-bit) 62 | if (mod == 0 && word == 2 && rm == 6) 63 | ilen = idx + 1 + word; 64 | // ([ip]+)disp32 (special case in 16/32-bit) 65 | else if (mod == 0 && word == 4 && rm == 5) 66 | ilen = idx + 1 + word; 67 | // [rm] (16/32/64-bit) 68 | else if (mod == 0) 69 | ilen = idx + 1; 70 | // [rm]+disp8 (16/32/64-bit) 71 | else if (mod == 1) 72 | ilen = idx + 1 + 1; 73 | // [rm]+disp16/32 (16/32/64-bit) 74 | else if (mod == 2) 75 | ilen = idx + 1 + word; 76 | // rm (16/32/64-bit only for call near 77 | else if (mod == 3 && reg == 2) 78 | ilen = idx + 1; 79 | // sim byte (32/64-bit) 80 | if (ilen && rm == 4 && word == 4 && mod != 3) { 81 | ilen += 1; 82 | // check sib special cases 83 | base = insn[idx+1] & 0x7; 84 | // base is disp32 (0) 85 | if (base == 5 && mod == 0)// || mod == 2)) 86 | ilen += word; 87 | } 88 | 89 | break; 90 | 91 | /* call far absolute static -- invalid in 64-bit! */ 92 | case 0x9a: 93 | // ptr16:16/32 (16/32-bit) 94 | ilen = idx + 1 + 2 + word; 95 | break; 96 | } 97 | 98 | return ilen; 99 | } 100 | 101 | int check_branch(unsigned char *from, unsigned char *to) 102 | { 103 | int i, matches; 104 | 105 | if (decode_ret(from) == 0) 106 | return 0; //TODO: log! 107 | 108 | for (i=8, matches=0; i < MAX_INSN - 1; i++) 109 | if (decode_call(to - MAX_INSN + i) == MAX_INSN - i) 110 | matches++; 111 | 112 | return (matches == 0); 113 | } 114 | -------------------------------------------------------------------------------- /src/windows/drv/exe/drvctl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "..\sys\kb.h" 7 | #include "..\..\..\common\decode.h" 8 | 9 | //XXX: SOURCES file does not accept sources from other directories .. that's 10 | //why the .c is inlcuded here 11 | #include "..\..\..\common\decode.c" 12 | 13 | #ifdef DETOUR 14 | extern VOID Log(LPCTSTR fmt, ...); 15 | #define LOG Log 16 | #else 17 | #include 18 | #define LOG(x, ...) fprintf(stderr, x, __VA_ARGS__) 19 | #endif 20 | 21 | static HANDLE dev; 22 | 23 | BOOL DriverInit() 24 | { 25 | dev = CreateFile( "\\\\.\\kb", GENERIC_READ | GENERIC_WRITE, 0, 26 | NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 27 | 28 | if (dev == INVALID_HANDLE_VALUE) { 29 | LOG("createfile failed: %d\n", GetLastError()); 30 | return FALSE; 31 | } 32 | 33 | return TRUE; 34 | } 35 | 36 | BOOL DriverFini() 37 | { 38 | if (!CloseHandle(dev)) { 39 | LOG("closehandle failed: %d\n", GetLastError()); 40 | return FALSE; 41 | } 42 | 43 | return TRUE; 44 | } 45 | 46 | BOOL EnableLBR() 47 | { 48 | ULONG bytesReturned; 49 | 50 | if (!DeviceIoControl(dev, (DWORD) IOCTL_KB_ENABLE_LBR, 51 | NULL, 0, NULL, 0, &bytesReturned, NULL)) { 52 | 53 | LOG("enable ioctl error: %d\n", GetLastError()); 54 | return FALSE; 55 | } 56 | 57 | return TRUE; 58 | } 59 | 60 | BOOL DisableLBR() 61 | { 62 | ULONG bytesReturned; 63 | int faults; 64 | 65 | if (!DeviceIoControl(dev, (DWORD) IOCTL_KB_DISABLE_LBR, NULL, 0, 66 | &faults, sizeof(faults), &bytesReturned, NULL)) { 67 | 68 | LOG("disable ioctl error: %d\n", GetLastError()); 69 | return FALSE; 70 | } 71 | 72 | LOG("faults: %d (bret=%lu)\n", faults, bytesReturned); 73 | 74 | return TRUE; 75 | } 76 | 77 | #define MAX_FN 128 78 | #define MAX_LN 256 79 | #define MAX_MSG 1024 80 | 81 | VOID Alert(__int64 from, __int64 to) 82 | { 83 | MEMORY_BASIC_INFORMATION mi; 84 | TCHAR name[MAX_FN], line[MAX_LN]; 85 | TCHAR msg[MAX_MSG]="kBouncer detected a bad branch!\r\r"; 86 | PDWORD addr; 87 | 88 | StringCchCopy(name, MAX_FN, TEXT("NULL")); 89 | 90 | if (VirtualQuery((LPCVOID)from, &mi, sizeof(mi))) { 91 | GetModuleFileName((HMODULE)mi.AllocationBase, name, MAX_FN); 92 | StringCchCopy(name, MAX_FN, _tcsrchr(name, '\\') + 1); 93 | } 94 | 95 | StringCchPrintf(line, MAX_LN, "From: %llx [%s:%d]\r", 96 | from, name, (PUCHAR)from - (PUCHAR)mi.AllocationBase); 97 | StringCchCat(msg, MAX_MSG, line); 98 | 99 | StringCchCopy(name, MAX_FN, TEXT("NULL")); 100 | 101 | if (VirtualQuery((LPCVOID)from, &mi, sizeof(mi))) { 102 | GetModuleFileName((HMODULE)mi.AllocationBase, name, MAX_FN); 103 | StringCchCopy(name, MAX_FN, _tcsrchr(name, '\\') + 1); 104 | } 105 | 106 | StringCchPrintf(line, MAX_LN, "To: %llx [%s:%d]\r", 107 | to, name, (PUCHAR)to - (PUCHAR)mi.AllocationBase); 108 | StringCchCat(msg, MAX_MSG, line); 109 | 110 | StringCchCat(msg, MAX_MSG, TEXT("Dump of destination bytes:\r")); 111 | 112 | addr = ((PDWORD) (to & 0xFFFFFFF0)) - 4; 113 | 114 | while (addr <= ((PDWORD) (to & 0xFFFFFFF0)) + 4) { 115 | StringCchPrintf(line, MAX_LN, "%p: %08lx %08lx %08lx %08lx\r", 116 | addr, addr[0], addr[1], addr[2], addr[3]); 117 | StringCchCat(msg, MAX_MSG, line); 118 | addr += 4; 119 | } 120 | 121 | MessageBox(NULL, msg, NULL, MB_OK | MB_ICONHAND | MB_TASKMODAL); 122 | } 123 | 124 | BOOL CheckLBR() 125 | { 126 | ULONG bytesReturned; 127 | BR br; 128 | 129 | if (!DeviceIoControl(dev, (DWORD) IOCTL_KB_CHECK_LBR, 130 | NULL, 0, &br, sizeof(br), &bytesReturned, NULL)) { 131 | 132 | LOG("check ioctl error: %d\n", GetLastError()); 133 | return FALSE; 134 | } 135 | 136 | if (bytesReturned == sizeof(br)) { 137 | LOG("bad br %llx -> %llx\n", br.from, br.to); 138 | Alert(br.from, br.to); 139 | ExitProcess(0x42); 140 | } 141 | 142 | return TRUE; 143 | } 144 | 145 | BOOL CheckLBRDump() 146 | { 147 | ULONG bytesReturned, i; 148 | BR lbr[LBR_SZ]; 149 | 150 | if (!DeviceIoControl(dev, (DWORD) IOCTL_KB_DUMP_LBR, 151 | NULL, 0, lbr, sizeof(lbr), &bytesReturned, NULL)) { 152 | 153 | LOG("dump ioctl error: %d\n", GetLastError()); 154 | return FALSE; 155 | } 156 | 157 | for (i=0; i < LBR_SZ; i++) { 158 | 159 | LOG("%2d: %llx -> %llx\n", i, lbr[i].from, lbr[i].to); 160 | 161 | // TODO: add exception handling for EXCEPTION_ACCESS_VIOLATION 162 | if (check_branch((PUCHAR)lbr[i].from, (PUCHAR)lbr[i].to)) { 163 | 164 | MessageBox(NULL, TEXT("got you!"), NULL, 165 | MB_OK | MB_ICONHAND | MB_TASKMODAL); 166 | ExitProcess(0x42); 167 | } 168 | } 169 | 170 | return TRUE; 171 | } 172 | 173 | -------------------------------------------------------------------------------- /src/windows/tools/ps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #pragma comment(lib, "psapi.lib") 6 | #pragma comment(lib, "advapi32.lib") 7 | 8 | // based on http://msdn.microsoft.com/en-us/library/windows/desktop/ms682621(v=vs.85).aspx and 9 | // simply compile with cl.exe .. 10 | 11 | #define MAX_MODS 1024 12 | #define MAX_PROCS 1024 13 | 14 | // globals 15 | HMODULE modules[MAX_MODS]; 16 | DWORD processes[MAX_PROCS]; 17 | 18 | void DisplayError(LPTSTR func) 19 | { 20 | LPTSTR buf; 21 | DWORD len; 22 | 23 | fprintf(stderr,"%s() error!\n", func); 24 | 25 | len = FormatMessage( 26 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 27 | NULL, GetLastError(), 28 | GetSystemDefaultLangID(), 29 | (LPTSTR) &buf, 0, NULL); 30 | 31 | if (len == 0) 32 | fprintf(stderr, "(could not get error message for %d)\n", 33 | GetLastError()); 34 | else { 35 | fprintf(stderr, "%s", buf); 36 | LocalFree(buf); 37 | } 38 | } 39 | 40 | int PrintModules(DWORD pid) 41 | { 42 | CHAR name[MAX_PATH]; 43 | HANDLE proc; 44 | DWORD needed, status; 45 | MODULEINFO info; 46 | unsigned int i; 47 | 48 | printf("\nProcess ID: %u ", pid); 49 | 50 | // Get a handle to the process. 51 | proc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 52 | FALSE, pid); 53 | if (proc == NULL) { 54 | DisplayError("OpenProcess"); 55 | return 1; 56 | } 57 | 58 | // Get the filename of the process 59 | if (GetProcessImageFileName(proc, name, MAX_PATH) == 0) { 60 | DisplayError("GetProcessImageFileName"); 61 | printf("(error getting name %d):\n", GetLastError()); 62 | } 63 | else 64 | printf("%s:\n", name); 65 | 66 | // Get a list of all the modules in this process. 67 | if (EnumProcessModulesEx(proc, modules, sizeof(modules), 68 | &needed, LIST_MODULES_ALL) == 0) { 69 | DisplayError("EnumProcessModulesEx"); 70 | CloseHandle(proc); 71 | return 1; 72 | } 73 | 74 | // check if maximum number of modules was exceeded 75 | if (needed > sizeof(modules)) { 76 | fprintf(stderr, "raise MAX_MODULES!!\n"); 77 | exit(1); 78 | } 79 | 80 | for (i=0; i < (needed / sizeof(HMODULE)); i++) { 81 | // Get the base name of the module 82 | if (GetModuleBaseName(proc, modules[i], name, MAX_PATH) == 0) { 83 | DisplayError("GetModuleBaseName"); 84 | printf("\tunknown", modules[i]); 85 | } 86 | else 87 | printf("\t%s", name, modules[i]); 88 | 89 | // Get the base and size for the module 90 | if (GetModuleInformation(proc, modules[i], 91 | &info, sizeof(info)) == 0) { 92 | DisplayError("GetModuleInformation"); 93 | printf(" N/A\n", modules[i]); 94 | } 95 | else 96 | printf(" %p %d\n", info.lpBaseOfDll, info.SizeOfImage); 97 | } 98 | 99 | 100 | // Release the handle to the process. 101 | CloseHandle(proc); 102 | 103 | return 0; 104 | } 105 | 106 | BOOL EnableDebugPrivilege() 107 | { 108 | HANDLE token; 109 | TOKEN_PRIVILEGES tp = { 0 }; 110 | LUID luid; 111 | DWORD cb = sizeof(TOKEN_PRIVILEGES); 112 | 113 | // look up the priviledge 114 | if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid) == 0) { 115 | DisplayError("LookupPrivilegeValue"); 116 | return FALSE; 117 | } 118 | 119 | // open our token 120 | if (OpenThreadToken(GetCurrentThread(), 121 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 122 | FALSE, &token) == 0) { 123 | 124 | if (GetLastError() == ERROR_NO_TOKEN) { 125 | if (!ImpersonateSelf(SecurityImpersonation)) 126 | return FALSE; 127 | 128 | if (OpenThreadToken(GetCurrentThread(), 129 | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 130 | FALSE, &token) == 0) { 131 | DisplayError("OpenThreadToken"); 132 | return FALSE; 133 | } 134 | } 135 | else { 136 | DisplayError("OpenThreadToken"); 137 | return FALSE; 138 | } 139 | } 140 | 141 | // setup the priviledge token 142 | tp.PrivilegeCount = 1; 143 | tp.Privileges[0].Luid = luid; 144 | tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 145 | 146 | // adjust the priviledge 147 | if (AdjustTokenPrivileges(token, FALSE, &tp, cb, NULL, NULL) == 0) { 148 | DisplayError("AdjustTokenPrivileges"); 149 | CloseHandle(token); 150 | return FALSE; 151 | } 152 | 153 | CloseHandle(token); 154 | 155 | return TRUE; 156 | } 157 | 158 | int main(int argc, char *argv[]) 159 | { 160 | DWORD needed; 161 | unsigned int i; 162 | 163 | // enable SeDebugPrivilege 164 | if (EnableDebugPrivilege() == FALSE) 165 | return 1; 166 | 167 | // Get the list of process identifiers 168 | if (EnumProcesses(processes, sizeof(processes), &needed) == 0) { 169 | DisplayError("EnumProcesses"); 170 | return 1; 171 | } 172 | 173 | if (needed > sizeof(processes)) { 174 | fprintf(stderr, "raise the maximum number of processes!\n"); 175 | return 1; 176 | } 177 | 178 | // Print the names of the modules for each process. 179 | for (i=0; i < (needed / sizeof(DWORD)); i++) 180 | PrintModules(processes[i]); 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /src/tools/anal.c: -------------------------------------------------------------------------------- 1 | #ifdef _WIN32 2 | #include 3 | #else 4 | #include 5 | #define MAX_PATH PATH_MAX 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "decode.h" 14 | 15 | /* 16 | * Maximum lengh of an x86 instruction 17 | */ 18 | #define MAX_INSN 16 19 | 20 | /* 21 | * Maximum number of images loaded in a process 22 | */ 23 | #define MAX_IMG 1024 24 | 25 | /* 26 | * Maximum number of system call wrapper functions 27 | */ 28 | #define MAX_FUNC 2048 29 | 30 | 31 | struct image { 32 | size_t start; 33 | size_t end; 34 | char *path; 35 | } images[MAX_IMG]; 36 | 37 | 38 | struct function { 39 | size_t address; 40 | char *name; 41 | char *img_path; 42 | } functions[MAX_FUNC]; 43 | 44 | 45 | int img_cnt = 0; 46 | 47 | int func_cnt = 0; 48 | 49 | 50 | char *lookup_addr(size_t addr); 51 | 52 | char *lookup_image(size_t addr) 53 | { 54 | int i; 55 | 56 | for (i=0; i < img_cnt; i++) 57 | if (addr >= images[i].start && addr <= images[i].end) 58 | return images[i].path; 59 | 60 | return NULL; 61 | } 62 | 63 | char *lookup_function(size_t addr) 64 | { 65 | int i; 66 | 67 | for (i=0; i < func_cnt; i++) 68 | if (functions[i].address == addr) 69 | return functions[i].name; 70 | 71 | return NULL; 72 | } 73 | 74 | 75 | int load_images_cb(FILE *fp) 76 | { 77 | char path[MAX_PATH]; 78 | size_t start, end; 79 | 80 | if (fscanf(fp, "%lx %lx %[^\n\r]\n", &start, &end, path) != 3) { 81 | fprintf(stderr, "cannot fscanf!\n"); 82 | return 1; 83 | } 84 | 85 | images[img_cnt].start = start; 86 | images[img_cnt].end = end; 87 | images[img_cnt].path = strdup(path); 88 | 89 | if (images[img_cnt].path == NULL) { 90 | fprintf(stderr, "cannot strdup!\n"); 91 | return 1; 92 | } 93 | 94 | img_cnt += 1; 95 | 96 | if (img_cnt == MAX_IMG) { 97 | fprintf(stderr, "raise MAX_IMG!\n"); 98 | return 1; 99 | } 100 | 101 | return 0; 102 | } 103 | 104 | 105 | int load_functions_cb(FILE *fp) 106 | { 107 | char path[MAX_PATH], name[MAX_PATH]; 108 | size_t address; 109 | 110 | if (fscanf(fp, "%lx %s %[^\n]\n", &address, name, path) != 3) { 111 | fprintf(stderr, "cannot fscanf!\n"); 112 | return 1; 113 | } 114 | 115 | //printf("%lx %s %s\n", address, name, path); 116 | 117 | functions[func_cnt].address = address; 118 | functions[func_cnt].name = strdup(name); 119 | functions[func_cnt].img_path = strdup(path); 120 | 121 | if (functions[func_cnt].name == NULL || 122 | functions[func_cnt].img_path == NULL) { 123 | fprintf(stderr, "cannot strdup!\n"); 124 | return 1; 125 | } 126 | 127 | func_cnt += 1; 128 | 129 | if (func_cnt == MAX_FUNC) { 130 | fprintf(stderr, "raise MAX_FUNC!\n"); 131 | return 1; 132 | } 133 | 134 | return 0; 135 | } 136 | 137 | int no_matches = 0; 138 | int more_matches = 0; 139 | int calls = 0; 140 | int returns = 0; 141 | int syscalls = 0; 142 | char *last_func=NULL; 143 | 144 | int process_branches_cb(FILE *fp) 145 | { 146 | size_t from, to; 147 | char src_s[4*MAX_INSN], dst_s[4*MAX_INSN]; 148 | char *sptr, *dptr, type[16]; 149 | unsigned char src[MAX_INSN], dst[MAX_INSN]; 150 | int tid, i, matches; 151 | 152 | if (fscanf(fp, "%s %d %lx %lx {%[^}]} {%[^}]}\n", 153 | type, &tid, &from, &to, src_s, dst_s) != 6) { 154 | fprintf(stderr, "cannot fscanf!\n"); 155 | return 1; 156 | } 157 | 158 | if (strcmp(type, "ret") == 0) { 159 | 160 | returns += 1; 161 | 162 | // 1. check that the instruction in the source can 163 | // be decoded to a return and that there was a call 164 | // instruction right above the return address 165 | for (i=0, sptr=src_s, dptr=dst_s; i < MAX_INSN; i++) { 166 | src[i] = strtoul(sptr, &sptr, 16); 167 | dst[i] = strtoul(dptr, &dptr, 16); 168 | } 169 | 170 | if (decode_ret(src) == 0) { 171 | fprintf(stderr, "ret src not a ret '%s'!\n", src_s); 172 | // return 0 and continue; that could be an iret.. 173 | return 0; 174 | } 175 | 176 | for (i=0, matches=0; i < MAX_INSN-1; i++) 177 | if (decode_call(&dst[i]) + i == MAX_INSN) 178 | matches++; 179 | 180 | if (matches == 0) { 181 | no_matches += 1; 182 | fprintf(stderr, "no call match %lx %s > %lx %s '%s'!\n", 183 | from, lookup_image(from), 184 | to, lookup_image(to), dst_s); 185 | } 186 | else if (matches > 1) 187 | more_matches += 1; 188 | 189 | // 2. 190 | 191 | } 192 | else if (strcmp(type, "call") == 0) { 193 | 194 | calls += 1; 195 | 196 | // 2. when there is a call to a function from ntdll.dll 197 | // start counting the number of returns 198 | //last_func = lookup_function(to); 199 | 200 | //if (last_func != NULL) 201 | // printf("call %s from %s\n", last_func, lookup_image(from)); 202 | 203 | } 204 | else if (strcmp(type, "sys") == 0) { 205 | 206 | syscalls += 1; 207 | 208 | // 2. print which ntdll call caused this system call 209 | //printf("syscall %ld from %s %s\n", to, 210 | // (last_func)?last_func:"unknown", 211 | // lookup_image(from)); 212 | } 213 | else { 214 | fprintf(stderr, "unknown type '%s'\n", type); 215 | return 1; 216 | } 217 | 218 | return 0; 219 | } 220 | 221 | 222 | int process_file(char *fname, int (*cb)(FILE *fp)) 223 | { 224 | FILE *fp; 225 | 226 | fp = fopen(fname, "r"); 227 | 228 | if (fp == NULL) { 229 | perror("fopen"); 230 | return 1; 231 | } 232 | 233 | for (;;) { 234 | 235 | if (cb(fp) != 0) 236 | return 1; 237 | 238 | if (ferror(fp)) { 239 | perror("fscanf"); 240 | return 1; 241 | } 242 | else if (feof(fp)) 243 | break; 244 | } 245 | 246 | fclose(fp); 247 | 248 | return 0; 249 | } 250 | 251 | 252 | int main(int argc, char *argv[]) 253 | { 254 | if (argc != 4) { 255 | fprintf(stderr, "usage: %s imgs funcs brs\n", argv[0]); 256 | return 1; 257 | } 258 | 259 | if (process_file(argv[1], load_images_cb) != 0) { 260 | fprintf(stderr, "failed to load %s\n", argv[1]); 261 | return 1; 262 | } 263 | 264 | printf("loaded %d images\n", img_cnt); 265 | 266 | if (process_file(argv[2], load_functions_cb) != 0) { 267 | fprintf(stderr, "failed to load %s\n", argv[2]); 268 | return 1; 269 | } 270 | 271 | printf("loaded %d functions\n", func_cnt); 272 | 273 | if (process_file(argv[3], process_branches_cb) != 0) { 274 | fprintf(stderr, "failed to proces %s\n", argv[3]); 275 | return 1; 276 | } 277 | 278 | printf("%d returns %d calls %d syscalls\n", returns, calls, syscalls); 279 | 280 | printf("call matches: %d not, %d more\n", no_matches, more_matches); 281 | 282 | return 0; 283 | } 284 | -------------------------------------------------------------------------------- /src/pintool/btr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "pin.H" 7 | #include "portability.H" 8 | 9 | using namespace std; 10 | 11 | /* 12 | * The ID of the buffer 13 | */ 14 | BUFFER_ID bufId; 15 | 16 | /* 17 | * The lock for I/O. 18 | */ 19 | PIN_LOCK fileLock; 20 | 21 | /* 22 | * There is an isolation bug in the Pin windows support that prevents 23 | * the pin tool from opening files ina callback routine. If a tool 24 | * does this, deadlock occurs. Instead, open one file in main, and 25 | * write the thread id along with the data. 26 | */ 27 | FILE *brf, *imgf, *funcf; 28 | 29 | /* 30 | * Number of OS pages for the buffer 31 | */ 32 | #define NUM_BUF_PAGES 1 33 | 34 | /* 35 | * Indirect branch instruction types 36 | */ 37 | #define RETURN 1 38 | #define JUMP 2 39 | #define CALL 3 40 | #define SYSENTER 4 41 | 42 | /* 43 | * Maximum length of an x86 instruction 44 | */ 45 | #define INSN_LEN 16 46 | 47 | /* 48 | * Name of the file where the branch trace is stored 49 | */ 50 | #define TRACE_FILE "branches.log" 51 | 52 | /* 53 | * Name of the file where the loaded images are stored 54 | */ 55 | #define IMAGES_FILE "images.log" 56 | 57 | /* 58 | * Name of the file where the functions are stored 59 | */ 60 | #define FUNCTIONS_FILE "functions.log" 61 | 62 | /* 63 | * Full path of the windows ntdll.dll 64 | */ 65 | //FIXME: this only works for 64-bit .. fix it for wow64 66 | #define NTDLL "C:\\Windows\\System32\\ntdll.dll" 67 | 68 | /* 69 | * Record of branches. 70 | */ 71 | typedef struct 72 | { 73 | THREADID tid; 74 | ADDRINT from; 75 | ADDRINT to; 76 | UINT32 type; 77 | } br_t; 78 | 79 | 80 | VOID Image(IMG img, VOID *v) 81 | { 82 | GetLock(&fileLock, 1); 83 | 84 | fprintf(imgf, "%lx %lx %s\n", IMG_LowAddress(img), IMG_HighAddress(img), 85 | IMG_Name(img).c_str()); 86 | 87 | ReleaseLock(&fileLock); 88 | } 89 | 90 | 91 | VOID Routine(RTN rtn, VOID *v) 92 | { 93 | GetLock(&fileLock, 1); 94 | 95 | string name = IMG_Name(SEC_Img(RTN_Sec(rtn))); 96 | 97 | if (_stricmp(name.c_str(), NTDLL) == 0) 98 | fprintf(funcf, "%lx %s %s\n", RTN_Address(rtn), 99 | RTN_Name(rtn).c_str(), name.c_str()); 100 | 101 | ReleaseLock(&fileLock); 102 | } 103 | 104 | 105 | VOID Instruction(INS ins, VOID *v) 106 | { 107 | if (INS_IsRet(ins)) 108 | 109 | INS_InsertFillBuffer(ins, IPOINT_BEFORE, bufId, 110 | IARG_THREAD_ID, offsetof(br_t, tid), 111 | IARG_INST_PTR, offsetof(br_t, from), 112 | IARG_RETURN_IP, offsetof(br_t, to), 113 | IARG_UINT32, RETURN, offsetof(br_t, type), 114 | IARG_END); 115 | 116 | else if (INS_IsSyscall(ins)) 117 | 118 | INS_InsertFillBuffer(ins, IPOINT_BEFORE, bufId, 119 | IARG_THREAD_ID, offsetof(br_t, tid), 120 | IARG_INST_PTR, offsetof(br_t, from), 121 | IARG_SYSCALL_NUMBER, offsetof(br_t, to), 122 | IARG_UINT32, SYSENTER, offsetof(br_t, type), 123 | IARG_END); 124 | 125 | else if (INS_IsCall(ins)) 126 | 127 | INS_InsertFillBuffer(ins, IPOINT_BEFORE, bufId, 128 | IARG_THREAD_ID, offsetof(br_t, tid), 129 | IARG_INST_PTR, offsetof(br_t, from), 130 | IARG_BRANCH_TARGET_ADDR, offsetof(br_t, to), 131 | IARG_UINT32, CALL, offsetof(br_t, type), 132 | IARG_END); 133 | 134 | //XXX: for now keep only returns 135 | #if 0 136 | else if (INS_IsIndirectBranchOrCall(ins)) { 137 | 138 | if (INS_IsCall(ins)) 139 | 140 | INS_InsertFillBuffer(ins, IPOINT_BEFORE, bufId, 141 | IARG_THREAD_ID, offsetof(br_t, tid), 142 | IARG_INST_PTR, offsetof(br_t, from), 143 | IARG_BRANCH_TARGET_ADDR, offsetof(br_t, to), 144 | IARG_UINT32, CALL, offsetof(br_t, type), 145 | IARG_END); 146 | 147 | else 148 | 149 | INS_InsertFillBuffer(ins, IPOINT_BEFORE, bufId, 150 | IARG_THREAD_ID, offsetof(br_t, tid), 151 | IARG_INST_PTR, offsetof(br_t, from), 152 | IARG_BRANCH_TARGET_ADDR, offsetof(br_t, to), 153 | IARG_UINT32, JUMP, offsetof(br_t, type), 154 | IARG_END); 155 | } 156 | #endif 157 | } 158 | 159 | 160 | VOID *BufferFull(BUFFER_ID id, THREADID tid, const CONTEXT *ctxt, VOID *buf, 161 | UINT64 numElements, VOID *v) 162 | { 163 | GetLock(&fileLock, 1); 164 | 165 | br_t *br = (br_t*) buf; 166 | unsigned char src[INSN_LEN], dst[INSN_LEN]; 167 | char src_s[INSN_LEN*3+1], dst_s[INSN_LEN*3+1]; 168 | size_t slen, dlen, i, j; 169 | 170 | for (i=0; i < numElements; i++, br++) { 171 | 172 | if (br->type == SYSENTER) { 173 | fprintf(brf, "sys %d %lx %lx {d3ad} {d3ad}\n", 174 | br->tid, br->from, br->to); 175 | continue; 176 | } 177 | else if (br->type == CALL) { 178 | fprintf(brf, "call %d %lx %lx {d3ad} {d3ad}\n", 179 | br->tid, br->from, br->to); 180 | continue; 181 | } 182 | 183 | slen = PIN_SafeCopy(src, (VOID*)br->from, INSN_LEN); 184 | dlen = PIN_SafeCopy(dst, (VOID*)(br->to-INSN_LEN), INSN_LEN); 185 | 186 | // it happens rarely for weird reasons .. skip it 187 | // most probably it's due to the fact that we copy the 188 | // memory whenever the buf is full and not when the br occurs 189 | if (slen != INSN_LEN || dlen != INSN_LEN) 190 | continue; 191 | 192 | for (j=0; j < INSN_LEN; j++) { 193 | sprintf(src_s + j*3, "%02x ", src[j]); 194 | sprintf(dst_s + j*3, "%02x ", dst[j]); 195 | } 196 | 197 | src_s[j*3] = dst_s[j*3] = '\0'; 198 | 199 | // FIXME: 64-bit addresses are truncated! 200 | fprintf(brf, "ret %d %lx %lx {%s} {%s}\n", 201 | br->tid, br->from, br->to, src_s, dst_s); 202 | } 203 | 204 | ReleaseLock(&fileLock); 205 | 206 | return buf; 207 | } 208 | 209 | 210 | VOID Fini(INT32 code, VOID *v) 211 | { 212 | GetLock(&fileLock, 1); 213 | 214 | fclose(brf); 215 | fclose(imgf); 216 | fclose(funcf); 217 | 218 | ReleaseLock(&fileLock); 219 | } 220 | 221 | 222 | int main(int argc, char *argv[]) 223 | { 224 | PIN_InitSymbols(); 225 | 226 | if (PIN_Init(argc, argv)) 227 | return 1; 228 | 229 | bufId = PIN_DefineTraceBuffer(sizeof(br_t), NUM_BUF_PAGES, 230 | BufferFull, 0); 231 | 232 | if (bufId == BUFFER_ID_INVALID) { 233 | fprintf(stderr, "Error: could not allocate initial buffer\n"); 234 | return 1; 235 | } 236 | 237 | InitLock(&fileLock); 238 | 239 | brf = fopen(TRACE_FILE, "w"); 240 | imgf = fopen(IMAGES_FILE, "w"); 241 | funcf = fopen(FUNCTIONS_FILE, "w"); 242 | 243 | if (brf == NULL || imgf == NULL || funcf == NULL) { 244 | fprintf(stderr, "Error: could not open output files\n"); 245 | return 1; 246 | } 247 | 248 | IMG_AddInstrumentFunction(Image, 0); 249 | 250 | RTN_AddInstrumentFunction(Routine, 0); 251 | 252 | INS_AddInstrumentFunction(Instruction, 0); 253 | 254 | PIN_AddFiniFunction(Fini, 0); 255 | 256 | PIN_StartProgram(); 257 | 258 | return 0; 259 | } 260 | -------------------------------------------------------------------------------- /src/windows/tools/loader.c: -------------------------------------------------------------------------------- 1 | // http://msdn.microsoft.com/en-us/library/aa366763%28VS.85%29.aspx 2 | // http://msdn.microsoft.com/en-us/library/aa366551(v=vs.85).aspx 3 | // http://msdn.microsoft.com/en-us/library/ms686958(v=vs.85).aspx 4 | #define UNICODE 5 | #define _UNICODE 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #pragma comment(lib, "dbghelp.lib") 13 | 14 | #define printf(fmt, ...) _ftprintf(stderr, TEXT(fmt), __VA_ARGS__) 15 | 16 | typedef NTSTATUS (NTAPI *pNtQueryInformationProcess)(HANDLE ProcessHandle, 17 | PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, 18 | ULONG ProcessInformationLength, PULONG ReturnLength); 19 | 20 | static HANDLE hProcess; // child process 21 | 22 | HANDLE CreateChildProcess(LPTSTR szCmdline) 23 | { 24 | PROCESS_INFORMATION piProcInfo; 25 | STARTUPINFO siStartInfo; 26 | BOOL bFuncRetn = FALSE; 27 | 28 | // set up members of the PROCESS_INFORMATION structure. 29 | ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); 30 | 31 | // set up members of the STARTUPINFO structure. 32 | ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); 33 | siStartInfo.cb = sizeof(STARTUPINFO); 34 | 35 | // create the child process. 36 | bFuncRetn = CreateProcess(NULL, 37 | szCmdline, // command line 38 | NULL, // process security attributes 39 | NULL, // primary thread security attributes 40 | TRUE, // handles are inherited 41 | DEBUG_PROCESS, // creation flags 42 | NULL, // use parent's environment 43 | NULL, // use parent's current directory 44 | &siStartInfo, // STARTUPINFO pointer 45 | &piProcInfo); // receives PROCESS_INFORMATION 46 | 47 | if (bFuncRetn == 0) { 48 | printf("CreateProcess failed (%d)\n", GetLastError()); 49 | return INVALID_HANDLE_VALUE; 50 | } 51 | 52 | CloseHandle(piProcInfo.hThread); 53 | 54 | return piProcInfo.hProcess; 55 | } 56 | 57 | BOOL AcroRd32exeFix(DEBUG_EVENT *e) 58 | { 59 | LPVOID pthree; 60 | CHAR three, four='4'; 61 | DWORD old, old2; 62 | 63 | #if 0 // XXX: the lpImageName is always NULL .. 64 | LPVOID name = NULL; 65 | TCHAR dllName[MAX_PATH]; 66 | LPVOID apip, api; 67 | ULONG len; 68 | 69 | printf("fix AcroRd.exe\n"); 70 | 71 | if (e->u.CreateProcessInfo.lpImageName == NULL) 72 | return FALSE; 73 | 74 | if (!ReadProcessMemory(hProcess, e->u.LoadDll.lpImageName, 75 | &name, sizeof(LPVOID), NULL)) { 76 | printf("cant read mem (%d)!!\n", GetLastError()); 77 | return FALSE; 78 | } 79 | 80 | if (name == NULL) { 81 | printf("name is null\n"); 82 | return FALSE; 83 | } 84 | 85 | if (!ReadProcessMemory(hProcess, name, dllName, MAX_PATH, NULL)) { 86 | printf("cant read mem (%d)\n!!", GetLastError()); 87 | return FALSE; 88 | } 89 | 90 | // at this point we have read the new module's name 91 | printf("loaded %s\n", dllName); 92 | 93 | if (_tcsstr(dllName, TEXT("AcroRd32.exe")) == NULL) { 94 | printf("not AcroRd32.exe\n"); 95 | return FALSE; 96 | } 97 | #endif 98 | // assume we only load AcroRd.exe .. 99 | 100 | printf("image base %lx\n", e->u.CreateProcessInfo.lpBaseOfImage); 101 | 102 | pthree = &((PCHAR)e->u.CreateProcessInfo.lpBaseOfImage)[0x717a]; 103 | 104 | if (!ReadProcessMemory(hProcess, pthree, &three, sizeof(three), NULL)) { 105 | printf("cant read mem (%d)\n!!", GetLastError()); 106 | return FALSE; 107 | } 108 | 109 | if (three != '3') { 110 | printf("read %x from %lx\n", three, pthree); 111 | return FALSE; 112 | } 113 | 114 | if (!VirtualProtectEx(hProcess, pthree, sizeof(four), 115 | PAGE_READWRITE, &old)) { 116 | printf("cant change perms (%d)\n!!", GetLastError()); 117 | return FALSE; 118 | } 119 | 120 | if (!WriteProcessMemory(hProcess, pthree, &four, sizeof(four), NULL)) { 121 | printf("cant write mem (%d)\n!!", GetLastError()); 122 | return FALSE; 123 | } 124 | 125 | if (!VirtualProtectEx(hProcess, pthree, sizeof(four), old, &old2)) { 126 | printf("cant change perms (%d)\n!!", GetLastError()); 127 | return FALSE; 128 | } 129 | 130 | printf("changed 3 to 4\n"); 131 | 132 | return TRUE; 133 | } 134 | 135 | BOOL ProcessLoadKernel32Event(DEBUG_EVENT *e) 136 | { 137 | LPVOID name = NULL; 138 | TCHAR dllName[MAX_PATH]; 139 | HMODULE hNtDll; 140 | pNtQueryInformationProcess qip; 141 | PROCESS_BASIC_INFORMATION pbi={0}; 142 | LPVOID apip, api; 143 | ULONG len; 144 | 145 | 146 | if (e->u.LoadDll.lpImageName == NULL) 147 | return FALSE; 148 | 149 | if (!ReadProcessMemory(hProcess, e->u.LoadDll.lpImageName, 150 | &name, sizeof(LPVOID), NULL)) { 151 | printf("cant read mem (%d)!!\n", GetLastError()); 152 | return FALSE; 153 | } 154 | 155 | if (name == NULL) { 156 | //printf("name is null\n"); 157 | return FALSE; 158 | } 159 | 160 | if (!ReadProcessMemory(hProcess, name, dllName, MAX_PATH, NULL)) { 161 | printf("cant read mem (%d)\n!!", GetLastError()); 162 | return FALSE; 163 | } 164 | 165 | // at this point we have read the new module's name 166 | 167 | if (_tcsstr(dllName, TEXT("kernel32.dll")) == NULL) { 168 | //printf("not kernel32.dll\n"); 169 | return FALSE; 170 | } 171 | 172 | if ((hNtDll=LoadLibrary(TEXT("ntdll.dll"))) == NULL) { 173 | printf("failed to load ntdll\n"); 174 | return FALSE; 175 | } 176 | 177 | qip = (pNtQueryInformationProcess) GetProcAddress(hNtDll, 178 | "NtQueryInformationProcess"); 179 | if (qip == NULL) { 180 | printf("failed to get qip\n"); 181 | FreeLibrary(hNtDll); 182 | return FALSE; 183 | } 184 | 185 | if (qip(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &len)) { 186 | printf("failed to get process info\n"); 187 | return FALSE; 188 | } 189 | 190 | printf("peb at %p\n", pbi.PebBaseAddress); 191 | 192 | // XXX for 64-bit: apip = &((DWORDLONG*)pbi.PebBaseAddress)[13]; 193 | apip = &((DWORD*)pbi.PebBaseAddress)[14]; 194 | 195 | if (!ReadProcessMemory(hProcess, apip, &api, sizeof(LPVOID), NULL)) { 196 | printf("cant read mem (%d)!!\n", GetLastError()); 197 | return FALSE; 198 | } 199 | 200 | printf("apiset at %p\n", api); 201 | 202 | // XXX hardcoded value .. should dynamically find the export symbol: 203 | // api_set_schema in the proxy kernel32.dll 204 | api = (PBYTE)e->u.LoadDll.lpBaseOfDll + 0x16000; 205 | 206 | #if 0 // FIXME: does not work .. 207 | if (SymInitialize(hProcess, NULL, TRUE) == FALSE) { 208 | printf("cannot init sym (%d)\n", GetLastError()); 209 | return FALSE; 210 | } 211 | 212 | sym->SizeOfStruct = sizeof(SYMBOL_INFO); 213 | sym->MaxNameLen = MAX_SYM_NAME; 214 | _tcscpy_s(snam, MAX_SYM_NAME, TEXT("WinExec")); 215 | 216 | if (!SymFromName(hProcess, (PCSTR)snam, sym)) { 217 | printf("could not find api_set_schema (%d)\n", GetLastError()); 218 | return FALSE; 219 | } 220 | #endif 221 | 222 | if (!WriteProcessMemory(hProcess, apip, &api, sizeof(LPVOID), NULL)) { 223 | printf("cant write mem (%d)!!\n", GetLastError()); 224 | return FALSE; 225 | } 226 | 227 | printf("changed apiset to %p\n", api); 228 | 229 | return TRUE; 230 | } 231 | 232 | 233 | VOID PrintException(DEBUG_EVENT *e) 234 | { 235 | PEXCEPTION_RECORD x = &e->u.Exception.ExceptionRecord; 236 | int i; 237 | 238 | printf("%x %x %lx %d\n", x->ExceptionCode, x->ExceptionFlags, 239 | x->ExceptionAddress, x->NumberParameters); 240 | 241 | for (i=0; i < x->NumberParameters; i++) 242 | printf("\t%lx\n", x->ExceptionInformation[i]); 243 | } 244 | 245 | 246 | void DebugLoop() 247 | { 248 | BOOL completed = FALSE; 249 | BOOL attached = FALSE; 250 | DEBUG_EVENT DebugEvent; 251 | 252 | while (!completed) { 253 | 254 | if (!WaitForDebugEvent(&DebugEvent, INFINITE)) { 255 | printf("Debug loop aborted\n"); 256 | ExitProcess(1); 257 | } 258 | 259 | switch (DebugEvent.dwDebugEventCode) { 260 | 261 | case CREATE_PROCESS_DEBUG_EVENT: 262 | AcroRd32exeFix(&DebugEvent); 263 | printf("CREATE_PROCESS_DEBUG_EVENT\n"); 264 | break; 265 | 266 | case EXIT_PROCESS_DEBUG_EVENT: 267 | case RIP_EVENT: 268 | printf("EXIT_PROCESS_DEBUG_EVENT\n"); 269 | //completed = TRUE; 270 | break; 271 | 272 | case CREATE_THREAD_DEBUG_EVENT: 273 | printf("CREATE_THREAD_DEBUG_EVENT\n"); 274 | break; 275 | 276 | case EXIT_THREAD_DEBUG_EVENT: 277 | printf("EXIT_THREAD_DEBUG_EVENT\n"); 278 | break; 279 | 280 | case LOAD_DLL_DEBUG_EVENT: 281 | //printf("LOAD_DLL_DEBUG_EVENT\n"); 282 | if (ProcessLoadKernel32Event(&DebugEvent)) 283 | ; //completed = TRUE; 284 | break; 285 | 286 | case EXCEPTION_DEBUG_EVENT: 287 | if (!attached) { 288 | // First exception is special 289 | printf("EXCEPTION_DEBUG_EVENT first\n"); 290 | attached = TRUE; 291 | } 292 | else if (DebugEvent.u.Exception.dwFirstChance) { 293 | printf("EXCEPTION_DEBUG_EVENT chanc\n"); 294 | PrintException(&DebugEvent); 295 | } 296 | else { 297 | printf("EXCEPTION_DEBUG_EVENT\n"); 298 | PrintException(&DebugEvent); 299 | ExitProcess(1); 300 | } 301 | break; 302 | } 303 | 304 | 305 | if (completed) 306 | DebugSetProcessKillOnExit(FALSE); 307 | 308 | // XXX nothing is handled (last flag bellow) 309 | if (!ContinueDebugEvent(DebugEvent.dwProcessId, 310 | DebugEvent.dwThreadId, 311 | DBG_EXCEPTION_NOT_HANDLED)) { 312 | printf("Error continuing debug event\n"); 313 | ExitProcess(1); 314 | } 315 | 316 | if (completed) { 317 | DebugActiveProcessStop(DebugEvent.dwProcessId); 318 | } 319 | } 320 | } 321 | 322 | 323 | int _tmain(int argc, TCHAR *argv[]) 324 | { 325 | BOOL res; 326 | 327 | printf("%x\n", EXCEPTION_ACCESS_VIOLATION); 328 | 329 | if (argc == 1) { 330 | printf("usage: %s PROGRAM\n", argv[0]); 331 | ExitProcess(1); 332 | } 333 | 334 | // Start the child process that will read the memory 335 | hProcess = CreateChildProcess(argv[1]); 336 | 337 | // Ensure this process is around until the child process terminates 338 | if (hProcess == INVALID_HANDLE_VALUE) { 339 | printf("failed to create the child process..\n"); 340 | ExitProcess(1); 341 | } 342 | 343 | printf("successfully created the child process, waiting..\n"); 344 | 345 | //WaitForSingleObject(hProcess, INFINITE); 346 | DebugLoop(); 347 | 348 | CloseHandle(hProcess); 349 | 350 | return 0; 351 | } 352 | -------------------------------------------------------------------------------- /src/windows/drv/sys/kb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Kernel Bouncer (kb) Windws Driver, based on the simple ioctl sample 3 | * (WDF version) from the WinDDK. 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | 10 | #include "kb.h" 11 | #include "..\..\..\common\decode.h" 12 | 13 | //XXX: SOURCES file does not accept sources from other directories .. that's 14 | //why the .c is inlcuded here 15 | #include "..\..\..\common\decode.c" 16 | 17 | 18 | #define LOG(x, ...) 19 | //XXX enable for debugging 20 | //#define LOG(msg, ...) \ 21 | // DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, msg, __VA_ARGS__) 22 | 23 | #define NT_DEVICE_NAME L"\\Device\\kb" 24 | #define DOS_DEVICE_NAME L"\\DosDevices\\kb" 25 | 26 | /* MSR register values for Nehalem */ 27 | #define MSR_IA32_DS_AREA 0x00000600 28 | #define MSR_LBR_SELECT 0x000001c8 29 | #define MSR_IA32_DEBUGCTL 0x000001d9 30 | #define MSR_LASTBRANCH_TOS 0x000001c9 31 | #define MSR_IA32_LASTBRANCH_0_FROM_IP 0x00000680 32 | #define MSR_IA32_LASTBRANCH_0_TO_IP 0x000006c0 33 | 34 | /* IA32_DEBUGCTL bits for Nehalem: */ 35 | #define IA32_DEBUGCTL_LBR (1UL << 0) 36 | #define IA32_DEBUGCTL_BTF (1UL << 1) 37 | #define IA32_DEBUGCTL_TR (1UL << 6) 38 | #define IA32_DEBUGCTL_BTS (1UL << 7) 39 | #define IA32_DEBUGCTL_BTINT (1UL << 8) 40 | #define IA32_DEBUGCTL_BTS_OFF_OS (1UL << 9) 41 | #define IA32_DEBUGCTL_BTS_OFF_USR (1UL << 10) 42 | #define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI (1UL << 11) 43 | #define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI (1UL << 12) 44 | #define IA32_DEBUGCTL_UNCORE_PMI_EN (1UL << 13) 45 | #define IA32_DEBUGCTL_FREEZE_WHILE_SMM_EN (1UL << 14) 46 | 47 | /* LBR_SELECT bits for Nehalem: */ 48 | #define LBR_SELECT_CPL_EQ_0 (1UL << 0) 49 | #define LBR_SELECT_CPL_NEQ_0 (1UL << 1) 50 | #define LBR_SELECT_JCC (1UL << 2) 51 | #define LBR_SELECT_NEAR_REL_CALL (1UL << 3) 52 | #define LBR_SELECT_NEAR_IND_CALL (1UL << 4) 53 | #define LBR_SELECT_NEAR_RET (1UL << 5) 54 | #define LBR_SELECT_NEAR_IND_JMP (1UL << 6) 55 | #define LBR_SELECT_NEAR_REL_JMP (1UL << 7) 56 | #define LBR_SELECT_FAR_BRANCH (1UL << 8) 57 | 58 | 59 | #define ITERATE_LBR(from, to, tos, i) for ( \ 60 | tos = __readmsr(MSR_LASTBRANCH_TOS) & (LBR_SZ - 1), \ 61 | from = __readmsr(MSR_IA32_LASTBRANCH_0_FROM_IP + tos) & (~0ULL>>1),\ 62 | to = __readmsr(MSR_IA32_LASTBRANCH_0_TO_IP + tos), \ 63 | i=0; i < LBR_SZ; i++, \ 64 | tos = (tos + 1) % LBR_SZ, \ 65 | from = __readmsr(MSR_IA32_LASTBRANCH_0_FROM_IP + tos) & (~0ULL>>1),\ 66 | to = __readmsr(MSR_IA32_LASTBRANCH_0_TO_IP + tos)) \ 67 | 68 | //XXX: all BTS related stuff were delete in revision 48 69 | 70 | 71 | // 72 | // Device driver routine declarations. 73 | // 74 | 75 | DRIVER_INITIALIZE DriverEntry; 76 | 77 | __drv_dispatchType(IRP_MJ_CREATE) 78 | __drv_dispatchType(IRP_MJ_CLOSE) 79 | DRIVER_DISPATCH 80 | KBCreateClose; 81 | 82 | __drv_dispatchType(IRP_MJ_DEVICE_CONTROL) 83 | DRIVER_DISPATCH 84 | KBDeviceControl; 85 | 86 | DRIVER_UNLOAD KBUnloadDriver; 87 | 88 | 89 | #ifdef ALLOC_PRAGMA 90 | #pragma alloc_text(INIT, DriverEntry) 91 | #pragma alloc_text(PAGE, KBCreateClose) 92 | #pragma alloc_text(PAGE, KBDeviceControl) 93 | #pragma alloc_text(PAGE, KBUnloadDriver) 94 | #endif // ALLOC_PRAGMA 95 | 96 | 97 | NTSTATUS 98 | DriverEntry( 99 | __in PDRIVER_OBJECT DriverObject, 100 | __in PUNICODE_STRING RegistryPath 101 | ) 102 | /*++ 103 | 104 | Routine Description: 105 | This routine is called by the kernel to initialize the driver. 106 | 107 | It creates the device object, fills in the dispatch entry points and 108 | completes the initialization. 109 | 110 | Arguments: 111 | DriverObject - a pointer to the object that represents this device 112 | driver. 113 | 114 | RegistryPath - a pointer to our Services key in the registry. 115 | 116 | Return Value: 117 | STATUS_SUCCESS if initialized; an error otherwise. 118 | 119 | --*/ 120 | 121 | { 122 | NTSTATUS ntStatus; 123 | UNICODE_STRING ntUnicodeString; // NT Device Name "\Device\kb" 124 | UNICODE_STRING ntWin32NameString; // Win32 Name "\DosDevices\kb" 125 | PDEVICE_OBJECT deviceObject = NULL; // ptr to device object 126 | 127 | UNREFERENCED_PARAMETER(RegistryPath); 128 | 129 | RtlInitUnicodeString(&ntUnicodeString, NT_DEVICE_NAME); 130 | 131 | ntStatus = IoCreateDevice( 132 | DriverObject, // Our Driver Object 133 | 0, // We don't use a device extension 134 | &ntUnicodeString, // Device name "\Device\kb" 135 | FILE_DEVICE_UNKNOWN, // Device type 136 | FILE_DEVICE_SECURE_OPEN,// Device characteristics 137 | FALSE, // Not an exclusive device 138 | &deviceObject); // Returned ptr to Device Object 139 | 140 | if (!NT_SUCCESS(ntStatus)) { 141 | LOG("kb.sys: Couldn't create the device object\n"); 142 | return ntStatus; 143 | } 144 | 145 | // 146 | // Initialize the driver object with this driver's entry points. 147 | // 148 | DriverObject->MajorFunction[IRP_MJ_CREATE] = KBCreateClose; 149 | DriverObject->MajorFunction[IRP_MJ_CLOSE] = KBCreateClose; 150 | DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KBDeviceControl; 151 | DriverObject->DriverUnload = KBUnloadDriver; 152 | 153 | // 154 | // Initialize a Unicode String containing the Win32 name 155 | // for our device. 156 | // 157 | RtlInitUnicodeString(&ntWin32NameString, DOS_DEVICE_NAME); 158 | 159 | // 160 | // Create a symbolic link between our device name and the Win32 name 161 | // 162 | ntStatus = IoCreateSymbolicLink(&ntWin32NameString, &ntUnicodeString); 163 | 164 | if (!NT_SUCCESS(ntStatus)) { 165 | // 166 | // Delete everything that this routine has allocated. 167 | // 168 | LOG("kb.sys: Couldn't create symbolic link\n"); 169 | IoDeleteDevice(deviceObject); 170 | } 171 | 172 | return ntStatus; 173 | } 174 | 175 | 176 | NTSTATUS 177 | KBCreateClose( 178 | PDEVICE_OBJECT DeviceObject, 179 | PIRP Irp 180 | ) 181 | /*++ 182 | 183 | Routine Description: 184 | 185 | This routine is called by the I/O system when the SIOCTL is opened or 186 | closed. 187 | 188 | No action is performed other than completing the request successfully. 189 | 190 | Arguments: 191 | 192 | DeviceObject - a pointer to the object that represents the device 193 | that I/O is to be done on. 194 | 195 | Irp - a pointer to the I/O Request Packet for this request. 196 | 197 | Return Value: 198 | 199 | NT status code 200 | 201 | --*/ 202 | 203 | { 204 | UNREFERENCED_PARAMETER(DeviceObject); 205 | 206 | PAGED_CODE(); 207 | 208 | Irp->IoStatus.Status = STATUS_SUCCESS; 209 | Irp->IoStatus.Information = 0; 210 | 211 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 212 | 213 | return STATUS_SUCCESS; 214 | } 215 | 216 | VOID 217 | KBUnloadDriver( 218 | __in PDRIVER_OBJECT DriverObject 219 | ) 220 | /*++ 221 | 222 | Routine Description: 223 | 224 | This routine is called by the I/O system to unload the driver. 225 | 226 | Any resources previously allocated must be freed. 227 | 228 | Arguments: 229 | 230 | DriverObject - a pointer to the object that represents our driver. 231 | 232 | Return Value: 233 | 234 | None 235 | --*/ 236 | 237 | { 238 | PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; 239 | UNICODE_STRING uniWin32NameString; 240 | 241 | PAGED_CODE(); 242 | 243 | // 244 | // Create counted string version of our Win32 device name. 245 | // 246 | RtlInitUnicodeString(&uniWin32NameString, DOS_DEVICE_NAME); 247 | 248 | 249 | // 250 | // Delete the link from our dev name to a name in the Win32 namespace. 251 | // 252 | IoDeleteSymbolicLink(&uniWin32NameString); 253 | 254 | if (deviceObject != NULL) 255 | IoDeleteDevice(deviceObject); 256 | } 257 | 258 | NTSTATUS 259 | KBDeviceControl( 260 | PDEVICE_OBJECT DeviceObject, 261 | PIRP Irp 262 | ) 263 | /*++ 264 | 265 | Routine Description: 266 | 267 | This routine is called by the I/O system to perform a device I/O 268 | control function. 269 | 270 | Arguments: 271 | 272 | DeviceObject - a pointer to the object that represents the device 273 | that I/O is to be done on. 274 | 275 | Irp - a pointer to the I/O Request Packet for this request. 276 | 277 | Return Value: 278 | 279 | NT status code 280 | 281 | --*/ 282 | 283 | { 284 | PIO_STACK_LOCATION irpSp; // Current stack location 285 | NTSTATUS ntStatus = STATUS_SUCCESS; // Assume success 286 | ULONG inBufLength; // Input buffer length 287 | ULONG outBufLength; // Output buffer length 288 | __int64 from, to, tos; 289 | // CHAR c=0; 290 | int bad_br, faults=0; 291 | ULONG i; 292 | PBR pbr; 293 | 294 | UNREFERENCED_PARAMETER(DeviceObject); 295 | 296 | PAGED_CODE(); 297 | 298 | irpSp = IoGetCurrentIrpStackLocation(Irp); 299 | inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; 300 | outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; 301 | 302 | // 303 | // Determine which I/O control code was specified. 304 | // 305 | switch (irpSp->Parameters.DeviceIoControl.IoControlCode) 306 | { 307 | // 308 | // Enable Last Branch Recording. This option makes more 309 | // sense on the Nehalem and later chips that provide a 310 | // stack of at least 16 pairs and also support branch 311 | // filtering (LBR_SELECT). 312 | // 313 | case IOCTL_KB_ENABLE_LBR: 314 | 315 | LOG("kb.sys: Called IOCTL_KB_ENABLE_LBR\n"); 316 | 317 | __writemsr(MSR_LBR_SELECT, 318 | LBR_SELECT_CPL_EQ_0 | 319 | //LBR_SELECT_CPL_NEQ_0 | 320 | LBR_SELECT_JCC | 321 | LBR_SELECT_NEAR_REL_CALL| 322 | LBR_SELECT_NEAR_IND_CALL| 323 | //LBR_SELECT_NEAR_RET | 324 | //LBR_SELECT_NEAR_IND_JMP | 325 | LBR_SELECT_NEAR_REL_JMP | 326 | LBR_SELECT_FAR_BRANCH); 327 | 328 | 329 | __writemsr(MSR_IA32_DEBUGCTL, IA32_DEBUGCTL_LBR); 330 | 331 | faults = 0; 332 | 333 | Irp->IoStatus.Information = 0; 334 | 335 | break; 336 | 337 | // 338 | // Dump the contents of the LBR stack. LBR must have been 339 | // enabled. 340 | // 341 | case IOCTL_KB_DUMP_LBR: 342 | 343 | LOG("kb.sys: Called IOCTL_KB_DUMP_LBR\n"); 344 | 345 | if (Irp->AssociatedIrp.SystemBuffer == NULL) { 346 | ntStatus = STATUS_INVALID_PARAMETER; 347 | break; 348 | } 349 | 350 | if (outBufLength < sizeof(BR) * LBR_SZ) { 351 | ntStatus = STATUS_BUFFER_TOO_SMALL; 352 | break; 353 | } 354 | 355 | 356 | pbr = (PBR) Irp->AssociatedIrp.SystemBuffer; 357 | 358 | ITERATE_LBR(from, to, tos, i) { 359 | LOG("%2d: %p -> %p\n", i, from, to); 360 | pbr[i].from = from; 361 | pbr[i].to = to; 362 | } 363 | 364 | Irp->IoStatus.Information = sizeof(BR) * LBR_SZ; 365 | 366 | break; 367 | 368 | // 369 | // Check the Last Branch Records. For each branch in LBR 370 | // check if the instruction previous to the destination is 371 | // a call. If not, stop and return the current branch. 372 | // 373 | case IOCTL_KB_CHECK_LBR: 374 | 375 | LOG("kb.sys: Called IOCTL_KB_CHECK_LBR\n"); 376 | 377 | if (Irp->AssociatedIrp.SystemBuffer == NULL) { 378 | ntStatus = STATUS_INVALID_PARAMETER; 379 | break; 380 | } 381 | 382 | if (outBufLength < sizeof(BR)) { 383 | ntStatus = STATUS_BUFFER_TOO_SMALL; 384 | break; 385 | } 386 | 387 | bad_br = FALSE; 388 | //#if 1 //null req 389 | ITERATE_LBR(from, to, tos, i) { 390 | try { 391 | ProbeForRead((PUCHAR)from, MAX_INSN, 1); 392 | ProbeForRead((PUCHAR)to-MAX_INSN, 393 | MAX_INSN, 1); 394 | //#if 1 //lbr 395 | if ((bad_br=check_branch((PUCHAR)from, 396 | (PUCHAR)to)) != 0) 397 | break; 398 | //#endif 399 | // c += *(PUCHAR)from; 400 | // c += *(PUCHAR)to; 401 | } except (EXCEPTION_EXECUTE_HANDLER) { 402 | faults += 1; 403 | } 404 | } 405 | //#if 1 //lbr 406 | 407 | if (bad_br) { 408 | LOG("bad br %llx -> %llx\n", from, to); 409 | pbr = (PBR) Irp->AssociatedIrp.SystemBuffer; 410 | pbr->from = from; 411 | pbr->to = to; 412 | Irp->IoStatus.Information = sizeof(BR); 413 | } 414 | else 415 | //#endif 416 | Irp->IoStatus.Information = 0; 417 | 418 | break; 419 | 420 | // 421 | // Disable Last Branch Recording. 422 | // 423 | case IOCTL_KB_DISABLE_LBR: 424 | 425 | LOG("kb.sys: Called IOCTL_KB_DISABLE_LBR\n"); 426 | 427 | __writemsr(MSR_LBR_SELECT, 0); 428 | 429 | __writemsr(MSR_IA32_DEBUGCTL, 0); 430 | 431 | if (outBufLength >= sizeof(faults)) { 432 | *(int*)Irp->AssociatedIrp.SystemBuffer = faults; 433 | Irp->IoStatus.Information = sizeof(faults); 434 | } 435 | else 436 | Irp->IoStatus.Information = 0; 437 | 438 | break; 439 | 440 | // 441 | // The specified I/O control code is unrecognized. 442 | // 443 | default: 444 | 445 | ntStatus = STATUS_INVALID_DEVICE_REQUEST; 446 | LOG("kb.sys: ERROR: unrecognized IOCTL %x\n", 447 | irpSp->Parameters. 448 | DeviceIoControl.IoControlCode); 449 | break; 450 | } 451 | 452 | // 453 | // Finish the I/O operation by simply completing the packet and return 454 | // the same status as in the packet itself. 455 | // 456 | Irp->IoStatus.Status = ntStatus; 457 | 458 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 459 | 460 | return ntStatus; 461 | } 462 | -------------------------------------------------------------------------------- /src/windows/detour/kb.cpp: -------------------------------------------------------------------------------- 1 | #define _WIN32_WINNT 0x0400 2 | #define WIN32 3 | #define NT 4 | 5 | #define DBG_TRACE 0 6 | 7 | #include 8 | #include 9 | 10 | #include "detours.h" 11 | 12 | extern "C" { 13 | #include "drvctl.h" 14 | } 15 | 16 | #define PULONG_PTR PVOID 17 | #define PLONG_PTR PVOID 18 | #define ULONG_PTR PVOID 19 | #define ENUMRESNAMEPROCA PVOID 20 | #define ENUMRESNAMEPROCW PVOID 21 | #define ENUMRESLANGPROCA PVOID 22 | #define ENUMRESLANGPROCW PVOID 23 | #define ENUMRESTYPEPROCA PVOID 24 | #define ENUMRESTYPEPROCW PVOID 25 | #define STGOPTIONS PVOID 26 | 27 | ////////////////////////////////////////////////////////////////////////////// 28 | 29 | #pragma warning(disable:4127) // Many of our asserts are constants. 30 | 31 | #define ASSERT_ALWAYS(x) \ 32 | do { \ 33 | if (!(x)) { \ 34 | Log(TEXT("ASSERT(%s) failed in %s, line %d.\n"), \ 35 | TEXT(#x), __FILE__, __LINE__); \ 36 | DebugBreak(); \ 37 | } \ 38 | } while (0) 39 | 40 | #ifndef NDEBUG 41 | #define ASSERT(x) ASSERT_ALWAYS(x) 42 | #else 43 | #define ASSERT(x) 44 | #endif 45 | 46 | #define UNUSED(c) (c) = (c) 47 | 48 | 49 | ////////////////////////////////////////////////////////////////////////////// 50 | static HMODULE s_hInst = NULL; 51 | static CHAR s_szDllPath[MAX_PATH]; 52 | 53 | extern "C" VOID Log(LPCTSTR fmt, ...); 54 | 55 | ////////////////////////////////////////////////////////////////////////////// 56 | // Trampolines 57 | // 58 | extern "C" { 59 | 60 | HANDLE (WINAPI * 61 | Real_CreateFileW)(LPCWSTR a0, 62 | DWORD a1, 63 | DWORD a2, 64 | LPSECURITY_ATTRIBUTES a3, 65 | DWORD a4, 66 | DWORD a5, 67 | HANDLE a6) 68 | = CreateFileW; 69 | 70 | BOOL (WINAPI * 71 | Real_WriteFile)(HANDLE hFile, 72 | LPCVOID lpBuffer, 73 | DWORD nNumberOfBytesToWrite, 74 | LPDWORD lpNumberOfBytesWritten, 75 | LPOVERLAPPED lpOverlapped) 76 | = WriteFile; 77 | BOOL (WINAPI * 78 | Real_FlushFileBuffers)(HANDLE hFile) 79 | = FlushFileBuffers; 80 | BOOL (WINAPI * 81 | Real_CloseHandle)(HANDLE hObject) 82 | = CloseHandle; 83 | 84 | BOOL (WINAPI * 85 | Real_WaitNamedPipeW)(LPCWSTR lpNamedPipeName, DWORD nTimeOut) 86 | = WaitNamedPipeW; 87 | BOOL (WINAPI * 88 | Real_SetNamedPipeHandleState)(HANDLE hNamedPipe, 89 | LPDWORD lpMode, 90 | LPDWORD lpMaxCollectionCount, 91 | LPDWORD lpCollectDataTimeout) 92 | = SetNamedPipeHandleState; 93 | 94 | DWORD (WINAPI * 95 | Real_GetCurrentProcessId)(VOID) 96 | = GetCurrentProcessId; 97 | VOID (WINAPI * 98 | Real_GetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime) 99 | = GetSystemTimeAsFileTime; 100 | 101 | VOID (WINAPI * 102 | Real_InitializeCriticalSection)(LPCRITICAL_SECTION lpSection) 103 | = InitializeCriticalSection; 104 | VOID (WINAPI * 105 | Real_EnterCriticalSection)(LPCRITICAL_SECTION lpSection) 106 | = EnterCriticalSection; 107 | VOID (WINAPI * 108 | Real_LeaveCriticalSection)(LPCRITICAL_SECTION lpSection) 109 | = LeaveCriticalSection; 110 | } 111 | 112 | #if _MSC_VER < 1300 113 | LPVOID (WINAPI * 114 | Real_HeapAlloc)(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes) 115 | = HeapAlloc; 116 | #else 117 | LPVOID (WINAPI * 118 | Real_HeapAlloc)(HANDLE hHeap, DWORD dwFlags, DWORD_PTR dwBytes) 119 | = HeapAlloc; 120 | #endif 121 | 122 | DWORD (WINAPI * Real_GetModuleFileNameW)(HMODULE a0, 123 | LPWSTR a1, 124 | DWORD a2) 125 | = GetModuleFileNameW; 126 | 127 | DWORD (WINAPI * Real_GetModuleFileNameA)(HMODULE a0, 128 | LPSTR a1, 129 | DWORD a2) 130 | = GetModuleFileNameA; 131 | 132 | BOOL (WINAPI * Real_CreateProcessW)(LPCWSTR a0, 133 | LPWSTR a1, 134 | LPSECURITY_ATTRIBUTES a2, 135 | LPSECURITY_ATTRIBUTES a3, 136 | BOOL a4, 137 | DWORD a5, 138 | LPVOID a6, 139 | LPCWSTR a7, 140 | struct _STARTUPINFOW* a8, 141 | LPPROCESS_INFORMATION a9) 142 | = CreateProcessW; 143 | 144 | HANDLE (WINAPI * Real_CreateFileA)(LPCSTR a0, 145 | DWORD a1, 146 | DWORD a2, 147 | LPSECURITY_ATTRIBUTES a3, 148 | DWORD a4, 149 | DWORD a5, 150 | HANDLE a6) 151 | = CreateFileA; 152 | 153 | BOOL (WINAPI * Real_VirtualProtect)(LPVOID a1, 154 | SIZE_T a2, 155 | DWORD a3, 156 | PDWORD a4) 157 | = VirtualProtect; 158 | 159 | ////////////////////////////////////////////////////////////////////////////// 160 | // Detours 161 | // 162 | 163 | BOOL WINAPI Mine_VirtualProtect( 164 | LPVOID lpAddress, 165 | SIZE_T dwSize, 166 | DWORD flNewProtect, 167 | PDWORD lpflOldProtect) 168 | { 169 | 170 | if (!CheckLBR()) 171 | Log("dump LBR failed %d\n", GetLastError()); 172 | else 173 | Log("dumped LBR!\n"); 174 | 175 | Log("VirtualProtect(%p, %ld, %x, %p)\n", 176 | lpAddress, dwSize, flNewProtect, lpflOldProtect); 177 | 178 | 179 | BOOL b = FALSE; 180 | __try { 181 | b = Real_VirtualProtect( 182 | lpAddress, dwSize, flNewProtect, lpflOldProtect); 183 | } __finally { 184 | Log("CreateFileA() -> %d\n", b); 185 | }; 186 | return b; 187 | } 188 | 189 | HANDLE WINAPI Mine_CreateFileA( 190 | LPCTSTR lpFileName, 191 | DWORD dwDesiredAccess, 192 | DWORD dwShareMode, 193 | LPSECURITY_ATTRIBUTES lpSecurityAttributes, 194 | DWORD dwCreationDisposition, 195 | DWORD dwFlagsAndAttributes, 196 | HANDLE hTemplateFile) 197 | { 198 | 199 | if (!CheckLBR()) 200 | Log("dump LBR failed %d\n", GetLastError()); 201 | else 202 | Log("dumped LBR!\n"); 203 | 204 | Log("CreateFileA(%s, %x, %x, %p, %x, %x, %d)\n", 205 | lpFileName, dwDesiredAccess, dwShareMode, 206 | lpSecurityAttributes, dwCreationDisposition, 207 | dwFlagsAndAttributes, hTemplateFile); 208 | 209 | 210 | HANDLE h = 0; 211 | __try { 212 | h = Real_CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, 213 | lpSecurityAttributes, dwCreationDisposition, 214 | dwFlagsAndAttributes, hTemplateFile); 215 | } __finally { 216 | Log("CreateFileA() -> %x\n", h); 217 | }; 218 | return h; 219 | } 220 | 221 | BOOL WINAPI Mine_CreateProcessW(LPCWSTR lpApplicationName, 222 | LPWSTR lpCommandLine, 223 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 224 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 225 | BOOL bInheritHandles, 226 | DWORD dwCreationFlags, 227 | LPVOID lpEnvironment, 228 | LPCWSTR lpCurrentDirectory, 229 | LPSTARTUPINFOW lpStartupInfo, 230 | LPPROCESS_INFORMATION lpProcessInformation) 231 | { 232 | Log("CreateProcessW(%ls,%ls,%p,%p,%x,%x,%p,%ls,%p,%p)\n", 233 | lpApplicationName, 234 | lpCommandLine, 235 | lpProcessAttributes, 236 | lpThreadAttributes, 237 | bInheritHandles, 238 | dwCreationFlags, 239 | lpEnvironment, 240 | lpCurrentDirectory, 241 | lpStartupInfo, 242 | lpProcessInformation); 243 | 244 | Log("Calling DetourCreateProcessWithDllW(,%hs)\n", s_szDllPath); 245 | 246 | BOOL rv = 0; 247 | __try { 248 | rv = DetourCreateProcessWithDllW(lpApplicationName, 249 | lpCommandLine, 250 | lpProcessAttributes, 251 | lpThreadAttributes, 252 | bInheritHandles, 253 | dwCreationFlags, 254 | lpEnvironment, 255 | lpCurrentDirectory, 256 | lpStartupInfo, 257 | lpProcessInformation, 258 | s_szDllPath, 259 | Real_CreateProcessW); 260 | } __finally { 261 | Log("CreateProcessW(,,,,,,,,,) -> %x\n", rv); 262 | }; 263 | return rv; 264 | } 265 | 266 | ////////////////////////////////////////////////////////////////////////////// 267 | // AttachDetours 268 | // 269 | VOID DetAttach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) 270 | { 271 | LONG l = DetourAttach(ppbReal, pbMine); 272 | if (l != 0) { 273 | Log("Attach failed: `%s': error %d\n", psz, l); 274 | } 275 | } 276 | 277 | VOID DetDetach(PVOID *ppbReal, PVOID pbMine, PCHAR psz) 278 | { 279 | LONG l = DetourDetach(ppbReal, pbMine); 280 | if (l != 0) { 281 | Log("Detach failed: `%s': error %d\n", psz, l); 282 | } 283 | } 284 | 285 | #define ATTACH(x) DetAttach(&(PVOID&)Real_##x,Mine_##x,#x) 286 | 287 | LONG AttachDetours(VOID) 288 | { 289 | DetourTransactionBegin(); 290 | DetourUpdateThread(GetCurrentThread()); 291 | 292 | ATTACH(CreateProcessW); 293 | ATTACH(CreateFileA); 294 | ATTACH(VirtualProtect); 295 | 296 | return DetourTransactionCommit(); 297 | } 298 | 299 | #define DETACH(x) DetDetach(&(PVOID&)Real_##x,Mine_##x,#x) 300 | 301 | LONG DetachDetours(VOID) 302 | { 303 | DetourTransactionBegin(); 304 | DetourUpdateThread(GetCurrentThread()); 305 | 306 | DETACH(CreateProcessW); 307 | DETACH(CreateFileA); 308 | DETACH(VirtualProtect); 309 | 310 | return DetourTransactionCommit(); 311 | } 312 | 313 | ////////////////////////////////////////////////////////////// Logging System. 314 | // 315 | 316 | #include 317 | #define MAX_MSG 1024 318 | #define S_DOTS TEXT("...\n") 319 | #define S_ERR TEXT("failed to sprintf\n") 320 | 321 | VOID Log(LPCTSTR fmt, ...) 322 | { 323 | HANDLE h; 324 | TCHAR msg[MAX_MSG]; 325 | HRESULT hr; 326 | DWORD written; 327 | va_list args; 328 | size_t len; 329 | 330 | h = Real_CreateFileA("kb.log", FILE_APPEND_DATA, 331 | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 332 | FILE_ATTRIBUTE_NORMAL, NULL); 333 | 334 | if (h == INVALID_HANDLE_VALUE) 335 | return; 336 | 337 | va_start(args, fmt); 338 | 339 | hr = StringCchVPrintf(msg, MAX_MSG, fmt, args); 340 | 341 | va_end(args); 342 | 343 | if (hr == STRSAFE_E_INSUFFICIENT_BUFFER) { 344 | StringCbCopy(&msg[MAX_MSG-5], sizeof(S_DOTS), S_DOTS); 345 | len = MAX_MSG; 346 | } 347 | else if (hr == STRSAFE_E_INVALID_PARAMETER) { 348 | StringCbCopy(msg, sizeof(S_ERR), S_ERR); 349 | len = sizeof(S_ERR); 350 | } 351 | else { 352 | StringCchLength(msg, MAX_MSG, &len); 353 | len = (len + 1) * sizeof(TCHAR); // null byte .. 354 | } 355 | 356 | //XXX no checks .. 357 | WriteFile(h, msg, len, &written, NULL); 358 | 359 | CloseHandle(h); 360 | } 361 | 362 | 363 | VOID NullExport() 364 | { 365 | } 366 | 367 | ////////////////////////////////////////////////////////////////////////////// 368 | // 369 | // DLL module information 370 | // 371 | BOOL ThreadAttach(HMODULE hDll) 372 | { 373 | (void)hDll; 374 | 375 | return TRUE; 376 | } 377 | 378 | BOOL ThreadDetach(HMODULE hDll) 379 | { 380 | (void)hDll; 381 | 382 | return TRUE; 383 | } 384 | 385 | BOOL ProcessAttach(HMODULE hDll) 386 | { 387 | 388 | WCHAR wzExePath[MAX_PATH]; 389 | 390 | s_hInst = hDll; 391 | Real_GetModuleFileNameA(s_hInst, s_szDllPath, ARRAYSIZE(s_szDllPath)); 392 | Real_GetModuleFileNameW(NULL, wzExePath, ARRAYSIZE(wzExePath)); 393 | 394 | Log("##########################################\n"); 395 | Log("### %ls\n", wzExePath); 396 | 397 | LONG error = AttachDetours(); 398 | if (error != NO_ERROR) { 399 | Log("### Error attaching detours: %d\n", error); 400 | } 401 | 402 | ThreadAttach(hDll); 403 | 404 | if (!DriverInit()) 405 | Log("### Error initializing driver: %d\n", GetLastError()); 406 | else if (!EnableLBR()) 407 | Log("### Error enabling: %d\n", GetLastError()); 408 | else 409 | Log("### driver initialized and LBR is enabled!\n"); 410 | 411 | CheckLBR(); 412 | 413 | return TRUE; 414 | } 415 | 416 | BOOL ProcessDetach(HMODULE hDll) 417 | { 418 | ThreadDetach(hDll); 419 | 420 | LONG error = DetachDetours(); 421 | if (error != NO_ERROR) { 422 | Log("### Error detaching detours: %d\n", error); 423 | } 424 | 425 | Log("### Closing.\n"); 426 | 427 | return TRUE; 428 | } 429 | 430 | BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, PVOID lpReserved) 431 | { 432 | (void)hModule; 433 | (void)lpReserved; 434 | 435 | switch (dwReason) { 436 | case DLL_PROCESS_ATTACH: 437 | DetourRestoreAfterWith(); 438 | return ProcessAttach(hModule); 439 | case DLL_PROCESS_DETACH: 440 | return ProcessDetach(hModule); 441 | case DLL_THREAD_ATTACH: 442 | return ThreadAttach(hModule); 443 | case DLL_THREAD_DETACH: 444 | return ThreadDetach(hModule); 445 | } 446 | return TRUE; 447 | } 448 | // 449 | ///////////////////////////////////////////////////////////////// End of File. 450 | --------------------------------------------------------------------------------