├── .appveyor.yml ├── BotMon ├── CMakeLists.txt ├── README.md ├── crypt.cpp ├── crypt.h ├── http.cpp ├── http.h ├── logger.cpp ├── logger.h ├── main.cpp ├── main.def ├── main.h ├── processmod.cpp ├── processmod.h ├── util.cpp └── util.h ├── CMakeLists.txt ├── ChangeColors ├── CMakeLists.txt ├── README.md ├── main.cpp ├── main.def ├── main.h └── sample │ └── colors.cfg ├── README.md └── ShowProc ├── README.md ├── ShowProc.wap ├── main.asm └── main.def /.appveyor.yml: -------------------------------------------------------------------------------- 1 | 2 | os: 3 | - Visual Studio 2015 4 | 5 | platform: x64 6 | - x64 7 | 8 | branches: 9 | only: 10 | - master 11 | 12 | environment: 13 | artifactName: $(APPVEYOR_PROJECT_NAME)-$(APPVEYOR_REPO_COMMIT)-$(CONFIGURATION) 14 | matrix: 15 | - env_arch: "x64" 16 | - env_arch: "x86" 17 | 18 | install: 19 | - cinst cmake 20 | - set PATH=C:\Program Files\CMake\bin;%PATH% 21 | 22 | build: 23 | verbosity: detailed 24 | 25 | configuration: 26 | - Release 27 | 28 | before_build: 29 | - mkdir build 30 | - cd build 31 | - if [%env_arch%]==[x64] ( 32 | cmake .. -A x64 ) 33 | - if [%env_arch%]==[x86] ( 34 | cmake .. ) 35 | - cmake -DCMAKE_INSTALL_PREFIX:PATH=%APPVEYOR_BUILD_FOLDER%/%APPVEYOR_REPO_COMMIT% .. 36 | 37 | build_script: 38 | - cmake --build . --config %CONFIGURATION% --target install 39 | 40 | after_build: 41 | - mkdir %artifactName% 42 | - cp %APPVEYOR_BUILD_FOLDER%/%APPVEYOR_REPO_COMMIT%/* %artifactName% 43 | 44 | artifacts: 45 | - path: build\%artifactName% 46 | -------------------------------------------------------------------------------- /BotMon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (BotMon) 3 | 4 | add_definitions(-DUNICODE -D_UNICODE) 5 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") 6 | 7 | set (srcs 8 | main.cpp 9 | util.cpp 10 | logger.cpp 11 | crypt.cpp 12 | http.cpp 13 | processmod.cpp 14 | ) 15 | 16 | set (hdrs 17 | main.h 18 | util.h 19 | logger.h 20 | crypt.h 21 | http.h 22 | processmod.h 23 | ) 24 | 25 | add_library (BotMon SHARED ${hdrs} ${srcs} main.def) 26 | 27 | #install 28 | INSTALL( TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT ${PROJECT_NAME} ) 29 | -------------------------------------------------------------------------------- /BotMon/README.md: -------------------------------------------------------------------------------- 1 | BotMon 2 | --- 3 | Sample set of functions useful for logging activity of a (malicious) bot.
4 | Allows to monitor usage of:
5 | + HTTP functions (connect/read/write etc) 6 | + encrypting/decrypting using Windows Crypto API 7 | + creating processes 8 | + writng into process memory 9 | 10 | Writes information about the event into a system log - and dumps the binary content into a specific folders.
11 | -------------------------------------------------------------------------------- /BotMon/crypt.cpp: -------------------------------------------------------------------------------- 1 | #include "crypt.h" 2 | #include 3 | #include 4 | 5 | #include "logger.h" 6 | 7 | using namespace std; 8 | 9 | BOOL 10 | _stdcall 11 | _cryptAcquireContextA( 12 | _Out_ HCRYPTPROV *phProv, 13 | _In_opt_ LPCSTR szContainer, 14 | _In_opt_ LPCSTR szProvider, 15 | _In_ DWORD dwProvType, 16 | _In_ DWORD dwFlags 17 | ) 18 | { 19 | Logger::append("[CRYPT] CryptAcquireContextA: dwProvType: %x dwFlags: %x", dwProvType, dwFlags); 20 | if (szContainer) { 21 | Logger::append("[CRYPT] CryptAcquireContextA: szContainer: %s", szContainer); 22 | } 23 | return CryptAcquireContextA(phProv, szContainer, szProvider, dwProvType, dwFlags); 24 | } 25 | 26 | BOOL 27 | _stdcall 28 | _cryptAcquireContextW( 29 | _Out_ HCRYPTPROV *phProv, 30 | _In_opt_ LPCWSTR szContainer, 31 | _In_opt_ LPCWSTR szProvider, 32 | _In_ DWORD dwProvType, 33 | _In_ DWORD dwFlags 34 | ) 35 | { 36 | Logger::append("[CRYPT] CryptAcquireContextW: dwProvType: %x dwFlags: %x", dwProvType, dwFlags); 37 | if (szContainer) { 38 | Logger::appendW(L"[CRYPT] CryptAcquireContextW: szContainer: %S", szContainer); 39 | } 40 | return CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags); 41 | } 42 | 43 | BOOL 44 | _stdcall 45 | _cryptGenRandomDummy( 46 | _In_ HCRYPTPROV hProv, 47 | _In_ DWORD dwLen, 48 | _Inout_updates_bytes_(dwLen) BYTE *pbBuffer 49 | ) 50 | { 51 | static char val = '0'; 52 | Logger::append("[CRYPT] CryptGenRandom intercepted: dwLen = %d (val = %c)", dwLen, val); 53 | BOOL is_ok = CryptGenRandom(hProv, dwLen, pbBuffer); 54 | if (is_ok) { 55 | memset(pbBuffer, val, dwLen); 56 | val++; 57 | if (val >= 0x7e) val = '0'; //reset 58 | } 59 | return is_ok; 60 | } 61 | 62 | BOOL 63 | _stdcall 64 | _cryptImportKey( 65 | _In_ HCRYPTPROV hProv, 66 | _In_reads_bytes_(dwDataLen) CONST BYTE *pbData, 67 | _In_ DWORD dwDataLen, 68 | _In_ HCRYPTKEY hPubKey, 69 | _In_ DWORD dwFlags, 70 | _Out_ HCRYPTKEY *phKey 71 | ) 72 | { 73 | if (pbData != NULL) { 74 | BLOBHEADER *blob = (BLOBHEADER*) pbData; 75 | Logger::append("[CRYPT] CryptImportKey: bType = %x aiKeyAlg = %x", blob->bType, blob->aiKeyAlg); 76 | Logger::logged_binary_dump(DIRNAME, "crypt_key", "[CRYPT]", (LPVOID)pbData, dwDataLen); 77 | } 78 | return CryptImportKey(hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey); 79 | } 80 | 81 | BOOL __stdcall _cryptDecrypt( 82 | IN HCRYPTKEY hKey, 83 | IN HCRYPTHASH hHash, 84 | IN BOOL Final, 85 | IN DWORD dwFlags, 86 | _Inout_updates_bytes_to_(*pdwDataLen, *pdwDataLen) BYTE *pbData, 87 | _Inout_ DWORD *pdwDataLen 88 | ) 89 | { 90 | BOOL res = CryptDecrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen); 91 | if (res == FALSE) { 92 | Logger::append("[DECRYPT] Failed"); 93 | return res; 94 | } 95 | if (pdwDataLen != NULL) { 96 | Logger::logged_binary_dump(DIRNAME, "decrypted", "[DECRYPT]", pbData, *pdwDataLen); 97 | } 98 | if (search_pe_hdr((BYTE*)pbData, *pdwDataLen)) { 99 | Logger::append("[DECRYPT] PE HEADER detected!"); 100 | } 101 | return res; 102 | } 103 | 104 | BOOL __declspec (dllexport) __stdcall _cryptEncrypt( 105 | IN HCRYPTKEY hKey, 106 | IN HCRYPTHASH hHash, 107 | IN BOOL Final, 108 | IN DWORD dwFlags, 109 | _Inout_updates_bytes_to_opt_(dwBufLen, *pdwDataLen) BYTE *pbData, 110 | _Inout_ DWORD *pdwDataLen, 111 | IN DWORD dwBufLen 112 | ) 113 | { 114 | if (pdwDataLen != NULL) { 115 | Logger::logged_binary_dump(DIRNAME, "before_encryption", "[ENCRYPT]", pbData, *pdwDataLen); 116 | } 117 | BOOL res = CryptEncrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen); 118 | if (res == FALSE) { 119 | Logger::append("[ENCRYPT] Failed"); 120 | } 121 | return res; 122 | } 123 | -------------------------------------------------------------------------------- /BotMon/crypt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #pragma comment(lib, "crypt32.lib") 7 | 8 | extern "C" { 9 | 10 | BOOL __declspec(dllexport) _stdcall _cryptAcquireContextA( 11 | _Out_ HCRYPTPROV *phProv, 12 | _In_opt_ LPCSTR szContainer, 13 | _In_opt_ LPCSTR szProvider, 14 | _In_ DWORD dwProvType, 15 | _In_ DWORD dwFlags 16 | ); 17 | 18 | BOOL __declspec(dllexport) _stdcall _cryptAcquireContextW( 19 | _Out_ HCRYPTPROV *phProv, 20 | _In_opt_ LPCWSTR szContainer, 21 | _In_opt_ LPCWSTR szProvider, 22 | _In_ DWORD dwProvType, 23 | _In_ DWORD dwFlags 24 | ); 25 | 26 | BOOL _stdcall _cryptGenRandomDummy( 27 | _In_ HCRYPTPROV hProv, 28 | _In_ DWORD dwLen, 29 | _Inout_updates_bytes_(dwLen) BYTE *pbBuffer 30 | ); 31 | 32 | 33 | BOOL __declspec(dllexport) _stdcall _cryptImportKey( 34 | _In_ HCRYPTPROV hProv, 35 | _In_reads_bytes_(dwDataLen) CONST BYTE *pbData, 36 | _In_ DWORD dwDataLen, 37 | _In_ HCRYPTKEY hPubKey, 38 | _In_ DWORD dwFlags, 39 | _Out_ HCRYPTKEY *phKey 40 | ); 41 | 42 | BOOL __declspec(dllexport) __stdcall _cryptDecrypt( 43 | IN HCRYPTKEY hKey, 44 | IN HCRYPTHASH hHash, 45 | IN BOOL Final, 46 | IN DWORD dwFlags, 47 | _Inout_updates_bytes_to_(*pdwDataLen, *pdwDataLen) BYTE *pbData, 48 | _Inout_ DWORD *pdwDataLen 49 | ); 50 | 51 | BOOL __declspec (dllexport) __stdcall _cryptEncrypt( 52 | IN HCRYPTKEY hKey, 53 | IN HCRYPTHASH hHash, 54 | IN BOOL Final, 55 | IN DWORD dwFlags, 56 | _Inout_updates_bytes_to_opt_(dwBufLen, *pdwDataLen) BYTE *pbData, 57 | _Inout_ DWORD *pdwDataLen, 58 | IN DWORD dwBufLen 59 | ); 60 | }; 61 | -------------------------------------------------------------------------------- /BotMon/http.cpp: -------------------------------------------------------------------------------- 1 | #include "http.h" 2 | #include 3 | #include 4 | 5 | #include "logger.h" 6 | #include "util.h" 7 | 8 | #define RESPONSE_FILE "response" 9 | #define RESPONSE_EXT ".bin" 10 | 11 | size_t g_CurrResp = 0; 12 | 13 | std::string make_filename(const std::string &base_name, size_t id, const std::string &ext) 14 | { 15 | std::stringstream ss; 16 | ss << base_name; 17 | ss << "_"; 18 | ss << id; 19 | ss << ext; 20 | return ss.str(); 21 | } 22 | 23 | //----- 24 | 25 | HINTERNET __stdcall _winHttpConnect( 26 | IN HINTERNET hSession, 27 | IN LPCWSTR pswzServerName, 28 | IN INTERNET_PORT nServerPort, 29 | _Reserved_ DWORD dwReserved) 30 | { 31 | Logger::append("[HTTP][conn] %S:%u", pswzServerName, static_cast(nServerPort)); 32 | return WinHttpConnect(hSession, pswzServerName, nServerPort, dwReserved); 33 | } 34 | 35 | HINTERNET __stdcall _winHttpOpenRequest(IN HINTERNET hConnect, 36 | IN LPCWSTR pwszVerb, 37 | IN LPCWSTR pwszObjectName, //url 38 | IN LPCWSTR pwszVersion, 39 | IN LPCWSTR pwszReferrer OPTIONAL, 40 | IN LPCWSTR FAR * ppwszAcceptTypes OPTIONAL, 41 | IN DWORD dwFlags) 42 | { 43 | if (pwszVerb) Logger::append("[HTTP][verb] %S", pwszVerb); 44 | if (pwszVersion) Logger::append("[HTTP][vers] %S", pwszVersion); 45 | if (pwszObjectName) Logger::append("[HTTP][obj ] %S", pwszObjectName); 46 | 47 | HINTERNET res = WinHttpOpenRequest(hConnect, pwszVerb, pwszObjectName, pwszVersion, pwszReferrer, ppwszAcceptTypes, dwFlags); 48 | //TODO: log the result 49 | return res; 50 | } 51 | 52 | BOOL __stdcall _winHttpSendRequest(IN HINTERNET hRequest, 53 | _In_reads_opt_(dwHeadersLength) LPCWSTR lpszHeaders, 54 | IN DWORD dwHeadersLength, 55 | _In_reads_bytes_opt_(dwOptionalLength) LPVOID lpOptional, 56 | IN DWORD dwOptionalLength, 57 | IN DWORD dwTotalLength, 58 | IN DWORD_PTR dwContext) 59 | { 60 | if (dwHeadersLength != 0 && lpszHeaders != NULL) { 61 | Logger::append("[HTTP][header] %S", lpszHeaders); 62 | } 63 | if (dwOptionalLength != 0) { 64 | Logger::append("[HTTP][optional]"); 65 | Logger::append_raw(lpOptional, dwOptionalLength, FALSE); 66 | Logger::append("[HTTP][/optional]"); 67 | Logger::logged_binary_dump(DIRNAME, "post", "[HTTP][optional]", lpOptional, dwOptionalLength); 68 | } 69 | BOOL res = WinHttpSendRequest(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext); 70 | if (res == FALSE) { 71 | Logger::append("[HTTP] Failed"); 72 | } 73 | return TRUE; // always true 74 | } 75 | 76 | BOOL __declspec(dllexport) __stdcall _winHttpReadData( 77 | IN HINTERNET hRequest, 78 | OUT LPVOID lpBuffer, 79 | IN DWORD dwNumberOfBytesToRead, 80 | OUT LPDWORD lpdwNumberOfBytesRead) 81 | { 82 | BOOL res = WinHttpReadData(hRequest, lpBuffer, dwNumberOfBytesToRead, lpdwNumberOfBytesRead); 83 | if (res == FALSE) return FALSE; 84 | 85 | if (*lpdwNumberOfBytesRead == 0) return res; 86 | DWORD printableSize = 0; 87 | if (has_printable_line(lpBuffer, *lpdwNumberOfBytesRead)) { 88 | Logger::append("[HTTP][response]"); 89 | printableSize = Logger::append_raw(lpBuffer, *lpdwNumberOfBytesRead, TRUE); 90 | Logger::append("[HTTP][/response]"); 91 | } 92 | //dump the raw content into a file: 93 | Logger::logged_binary_dump(DIRNAME, "responses", "[HTTP][rcvd]", lpBuffer, *lpdwNumberOfBytesRead); 94 | 95 | //check for a PE file: 96 | if (search_pe_hdr((BYTE*)lpBuffer, *lpdwNumberOfBytesRead)) { 97 | Logger::append("[HTTP] PE HEADER detected!"); 98 | } 99 | /* 100 | const char blacklisted[] ="/25/"; 101 | if (starts_with(lpBuffer, *lpdwNumberOfBytesRead, blacklisted)) { 102 | // this is the blacklisted command! 103 | return FALSE; 104 | }*/ 105 | return res; 106 | } 107 | 108 | BOOL BOTMON_API __stdcall _winHttpReceiveResponseFromFile( 109 | IN HINTERNET hRequest, 110 | IN LPVOID lpReserved 111 | ) 112 | { 113 | std::string resp_file = make_filename(RESPONSE_FILE, g_CurrResp, RESPONSE_EXT); 114 | if (get_file_size(resp_file.c_str()) != 0) { 115 | return TRUE; 116 | } 117 | return FALSE; 118 | } 119 | 120 | 121 | BOOL BOTMON_API __stdcall _winHttpQueryDataAvailableFromFile( 122 | IN HINTERNET hRequest, 123 | OUT LPDWORD lpdwNumberOfBytesAvailable 124 | ) 125 | { 126 | const std::string resp_file = make_filename(RESPONSE_FILE, g_CurrResp, RESPONSE_EXT); 127 | size_t size = get_file_size(resp_file.c_str()); 128 | if (lpdwNumberOfBytesAvailable) { 129 | (*lpdwNumberOfBytesAvailable) = size; 130 | } 131 | return TRUE; 132 | } 133 | 134 | 135 | BOOL BOTMON_API __stdcall _winHttpReadDataFromFile( 136 | IN HINTERNET hRequest, 137 | OUT LPVOID lpBuffer, 138 | IN DWORD dwNumberOfBytesToRead, 139 | OUT LPDWORD lpdwNumberOfBytesRead 140 | ) 141 | { 142 | if (!lpBuffer) return FALSE; 143 | 144 | const std::string resp_file = make_filename(RESPONSE_FILE, g_CurrResp, RESPONSE_EXT); 145 | FILE *fp = fopen(resp_file.c_str(), "rb"); 146 | if (!fp) return FALSE; 147 | 148 | size_t readSize = fread(lpBuffer, 1, dwNumberOfBytesToRead, fp); 149 | fclose(fp); 150 | 151 | if (lpdwNumberOfBytesRead) { 152 | (*lpdwNumberOfBytesRead) = readSize; 153 | } 154 | g_CurrResp++; 155 | return TRUE; 156 | } 157 | -------------------------------------------------------------------------------- /BotMon/http.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #pragma comment(lib, "WinHttp.lib") 7 | 8 | #define BOTMON_API __declspec(dllexport) 9 | 10 | extern "C" { 11 | 12 | HINTERNET BOTMON_API __stdcall _winHttpConnect( 13 | IN HINTERNET hSession, 14 | IN LPCWSTR pswzServerName, 15 | IN INTERNET_PORT nServerPort, 16 | _Reserved_ DWORD dwReserved 17 | ); 18 | 19 | HINTERNET BOTMON_API __stdcall _winHttpOpenRequest( 20 | IN HINTERNET hConnect, 21 | IN LPCWSTR pwszVerb, 22 | IN LPCWSTR pwszObjectName, 23 | IN LPCWSTR pwszVersion, 24 | IN LPCWSTR pwszReferrer OPTIONAL, 25 | IN LPCWSTR FAR * ppwszAcceptTypes OPTIONAL, 26 | IN DWORD dwFlags 27 | ); 28 | 29 | BOOL BOTMON_API __stdcall _winHttpSendRequest( 30 | IN HINTERNET hRequest, 31 | _In_reads_opt_(dwHeadersLength) LPCWSTR lpszHeaders, 32 | IN DWORD dwHeadersLength, 33 | _In_reads_bytes_opt_(dwOptionalLength) LPVOID lpOptional, 34 | IN DWORD dwOptionalLength, 35 | IN DWORD dwTotalLength, 36 | IN DWORD_PTR dwContext 37 | ); 38 | 39 | BOOL BOTMON_API __stdcall _winHttpReadData( 40 | IN HINTERNET hRequest, 41 | OUT LPVOID lpBuffer, 42 | IN DWORD dwNumberOfBytesToRead, 43 | OUT LPDWORD lpdwNumberOfBytesRead 44 | ); 45 | 46 | BOOL BOTMON_API __stdcall _winHttpReceiveResponseFromFile( 47 | IN HINTERNET hRequest, 48 | IN LPVOID lpReserved 49 | ); 50 | 51 | BOOL BOTMON_API __stdcall _winHttpQueryDataAvailableFromFile( 52 | IN HINTERNET hRequest, 53 | OUT LPDWORD lpdwNumberOfBytesAvailable 54 | ); 55 | 56 | BOOL BOTMON_API __stdcall _winHttpReadDataFromFile( 57 | IN HINTERNET hRequest, 58 | OUT LPVOID lpBuffer, 59 | IN DWORD dwNumberOfBytesToRead, 60 | OUT LPDWORD lpdwNumberOfBytesRead 61 | ); 62 | 63 | }; 64 | -------------------------------------------------------------------------------- /BotMon/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "logger.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | void make_out_filename(const LPWSTR dirname, const LPCSTR prefix, LPSTR out_filename) 9 | { 10 | wchar_t current_dir[MAX_PATH]; 11 | GetCurrentDirectoryW(MAX_PATH, current_dir); 12 | 13 | CreateDirectoryW(dirname, NULL); 14 | 15 | static time_t t1 = 0; 16 | if (time == 0) { 17 | t1 = time(NULL); 18 | srand(t1); 19 | } 20 | _snprintf(out_filename, MAX_PATH, 21 | "%S\\%S\\%s_%llu_%u.bin", 22 | current_dir, 23 | dirname, 24 | prefix, 25 | static_cast(time(NULL)), 26 | static_cast(rand()) 27 | ); 28 | } 29 | 30 | BOOL dump_binary(LPSTR out_filename, BYTE *pbData, DWORD dwDataLen) 31 | { 32 | FILE *fp = fopen(out_filename, "wb"); 33 | if (fp == NULL) return FALSE; 34 | if (dwDataLen != 0) { 35 | fwrite(pbData, 1, dwDataLen, fp); 36 | } 37 | fclose(fp); 38 | return TRUE; 39 | } 40 | 41 | //---- 42 | 43 | BOOL Logger::append(const char* format, ...) 44 | { 45 | if (format == NULL) { 46 | return FALSE; 47 | } 48 | va_list argptr; 49 | // Initializing arguments to store all values after format 50 | va_start(argptr, format); 51 | 52 | char line[MAX_LINE]; 53 | int printed = vsnprintf(line, MAX_LINE, format, argptr); 54 | 55 | //cleaning up the list: 56 | va_end(argptr); 57 | if (printed <= 0) return FALSE; 58 | 59 | OutputDebugStringA(line); 60 | return TRUE; 61 | } 62 | 63 | BOOL Logger::appendW(const wchar_t* format, ...) 64 | { 65 | if (format == NULL) { 66 | return FALSE; 67 | } 68 | va_list argptr; 69 | // Initializing arguments to store all values after format 70 | va_start(argptr, format); 71 | _locale_t locale = { 0 }; 72 | wchar_t line[MAX_LINE]; 73 | int printed = _vsnwprintf_s(line, MAX_LINE, format, argptr); 74 | 75 | //cleaning up the list: 76 | va_end(argptr); 77 | if (printed <= 0) return FALSE; 78 | 79 | OutputDebugStringW(line); 80 | return TRUE; 81 | } 82 | 83 | DWORD Logger::append_raw(LPVOID lpOptional, const DWORD dwOptionalLength, BOOL stopOnNonPrintable) 84 | { 85 | if (lpOptional == NULL) return 0; 86 | 87 | char *line = new char [dwOptionalLength + 1]; 88 | char *line_ptr = line; 89 | 90 | char *in_ptr = (char*) lpOptional; 91 | DWORD i = 0; 92 | for (; i < dwOptionalLength; i++) { 93 | char c = in_ptr[i]; 94 | if (!isprint(c)) { 95 | if (stopOnNonPrintable) break; 96 | line_ptr[i] = '.'; 97 | } else { 98 | line_ptr[i] = ((char*)lpOptional)[i]; 99 | } 100 | } 101 | line[i] = '\0'; 102 | OutputDebugStringA(line); 103 | return i; 104 | } 105 | 106 | BOOL Logger::logged_binary_dump(LPWSTR dir_name, LPCSTR file_prefix, LPCSTR log_line_prefix, LPVOID buffer, DWORD bufferSize) 107 | { 108 | if (buffer == NULL || bufferSize == 0) { 109 | return FALSE; 110 | } 111 | char out_filename[MAX_PATH]; 112 | make_out_filename(dir_name, file_prefix, out_filename); 113 | if (dump_binary(out_filename, (BYTE*) buffer, bufferSize)) { 114 | Logger::append("%s %u saved to: %s", log_line_prefix, bufferSize, out_filename); 115 | return TRUE; 116 | } 117 | return FALSE; 118 | } -------------------------------------------------------------------------------- /BotMon/logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "util.h" 5 | 6 | #define DIRNAME L"BotMon" 7 | 8 | #define MAX_LINE 1024 9 | 10 | namespace Logger 11 | { 12 | BOOL append(const char* format, ...); 13 | 14 | BOOL appendW(const wchar_t* format, ...); 15 | 16 | //returns: size of the appended content: 17 | DWORD append_raw(LPVOID lpOptional, const DWORD dwOptionalLength, BOOL stopOnNonPrintable); 18 | 19 | //dump content into a binary file, log the event: 20 | BOOL logged_binary_dump(LPWSTR dir_name, LPCSTR file_prefix, LPCSTR log_line_prefix, LPVOID buffer, DWORD bufferSize); 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /BotMon/main.cpp: -------------------------------------------------------------------------------- 1 | #include "crypt.h" 2 | #include "http.h" 3 | #include "processmod.h" 4 | 5 | using namespace std; 6 | 7 | BOOL WINAPI DllMain (HANDLE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 8 | { 9 | switch (fdwReason) 10 | { 11 | case DLL_PROCESS_ATTACH: 12 | case DLL_THREAD_ATTACH: 13 | case DLL_THREAD_DETACH: 14 | case DLL_PROCESS_DETACH: 15 | break; 16 | } 17 | 18 | return TRUE; 19 | } 20 | -------------------------------------------------------------------------------- /BotMon/main.def: -------------------------------------------------------------------------------- 1 | LIBRARY BotMon 2 | EXPORTS _winHttpConnect 3 | EXPORTS _winHttpOpenRequest 4 | EXPORTS _winHttpSendRequest 5 | EXPORTS _winHttpReadData 6 | EXPORTS _winHttpReceiveResponseFromFile 7 | EXPORTS _winHttpQueryDataAvailableFromFile 8 | EXPORTS _winHttpReadDataFromFile 9 | EXPORTS _cryptDecrypt 10 | EXPORTS _cryptEncrypt 11 | EXPORTS _cryptImportKey 12 | EXPORTS _cryptAcquireContextA 13 | EXPORTS _cryptAcquireContextW 14 | EXPORTS _cryptGenRandomDummy 15 | EXPORTS _writeProcessMemory 16 | EXPORTS _createProcessW 17 | EXPORTS _createProcessA 18 | -------------------------------------------------------------------------------- /BotMon/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /BotMon/processmod.cpp: -------------------------------------------------------------------------------- 1 | #include "processmod.h" 2 | 3 | #include "logger.h" 4 | 5 | BOOL __declspec(dllexport) WINAPI _createProcessW( 6 | _In_opt_ LPCWSTR lpApplicationName, 7 | _Inout_opt_ LPWSTR lpCommandLine, 8 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 9 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 10 | _In_ BOOL bInheritHandles, 11 | _In_ DWORD dwCreationFlags, 12 | _In_opt_ LPVOID lpEnvironment, 13 | _In_opt_ LPCWSTR lpCurrentDirectory, 14 | _In_ LPSTARTUPINFOW lpStartupInfo, 15 | _Out_ LPPROCESS_INFORMATION lpProcessInformation 16 | ) 17 | { 18 | BOOL res = CreateProcessW( 19 | lpApplicationName, 20 | lpCommandLine, 21 | lpProcessAttributes, 22 | lpThreadAttributes, 23 | bInheritHandles, 24 | dwCreationFlags, 25 | lpEnvironment, 26 | lpCurrentDirectory, 27 | lpStartupInfo, 28 | lpProcessInformation 29 | ); 30 | if (res == FALSE) { 31 | Logger::append("[PROCESS][CREATE_W] %S : %S, flags: %x -> failed", lpApplicationName, lpCommandLine, dwCreationFlags); 32 | } 33 | else { 34 | Logger::append("[PROCESS][CREATE_W] %S : %S, flags: %x -> PID: %d", lpApplicationName, lpCommandLine, dwCreationFlags, lpProcessInformation->dwProcessId); 35 | } 36 | return res; 37 | } 38 | 39 | BOOL __declspec(dllexport) WINAPI _createProcessA( 40 | _In_opt_ LPCSTR lpApplicationName, 41 | _Inout_opt_ LPSTR lpCommandLine, 42 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 43 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 44 | _In_ BOOL bInheritHandles, 45 | _In_ DWORD dwCreationFlags, 46 | _In_opt_ LPVOID lpEnvironment, 47 | _In_opt_ LPCSTR lpCurrentDirectory, 48 | _In_ LPSTARTUPINFOA lpStartupInfo, 49 | _Out_ LPPROCESS_INFORMATION lpProcessInformation 50 | ) 51 | { 52 | BOOL res = CreateProcessA(lpApplicationName, lpCommandLine, 53 | lpProcessAttributes, 54 | lpThreadAttributes, 55 | bInheritHandles, 56 | dwCreationFlags, 57 | lpEnvironment, 58 | lpCurrentDirectory, 59 | lpStartupInfo, 60 | lpProcessInformation 61 | ); 62 | if (res == FALSE) { 63 | Logger::append("[PROCESS][CREATE_A] %s : %s, flags: %x -> failed", lpApplicationName, lpCommandLine, dwCreationFlags); 64 | } 65 | else { 66 | Logger::append("[PROCESS][CREATE_A] %s : %s, flags: %x -> PID: %d", lpApplicationName, lpCommandLine, dwCreationFlags, lpProcessInformation->dwProcessId); 67 | } 68 | return res; 69 | } 70 | 71 | BOOL __declspec(dllexport) __stdcall _writeProcessMemory( 72 | IN HANDLE hProcess, 73 | IN LPVOID lpBaseAddress, 74 | _In_reads_bytes_(nSize) LPCVOID lpBuffer, 75 | IN SIZE_T nSize, 76 | _Out_opt_ SIZE_T * lpNumberOfBytesWritten 77 | ) 78 | { 79 | DWORD pid = GetProcessId(hProcess); 80 | 81 | Logger::append("[PROCESS][WRITE] PID: %d", pid); 82 | Logger::logged_binary_dump(DIRNAME, "write_mem", "[PROCESS][WRITE]", (BYTE*)lpBuffer, nSize); 83 | 84 | if (search_pe_hdr((BYTE*)lpBuffer, nSize)) { 85 | Logger::append("[PROCESS][WRITE] PE HEADER detected!"); 86 | } 87 | 88 | BOOL res = WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten); 89 | if (res == FALSE) Logger::append("[PROCESS][WRITE] Failed"); 90 | return res; 91 | } 92 | -------------------------------------------------------------------------------- /BotMon/processmod.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | extern "C" { 6 | 7 | BOOL __declspec(dllexport) __stdcall _writeProcessMemory( 8 | IN HANDLE hProcess, 9 | IN LPVOID lpBaseAddress, 10 | _In_reads_bytes_(nSize) LPCVOID lpBuffer, 11 | IN SIZE_T nSize, 12 | _Out_opt_ SIZE_T * lpNumberOfBytesWritten 13 | ); 14 | 15 | BOOL __declspec(dllexport) WINAPI _createProcessW( 16 | _In_opt_ LPCWSTR lpApplicationName, 17 | _Inout_opt_ LPWSTR lpCommandLine, 18 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 19 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 20 | _In_ BOOL bInheritHandles, 21 | _In_ DWORD dwCreationFlags, 22 | _In_opt_ LPVOID lpEnvironment, 23 | _In_opt_ LPCWSTR lpCurrentDirectory, 24 | _In_ LPSTARTUPINFOW lpStartupInfo, 25 | _Out_ LPPROCESS_INFORMATION lpProcessInformation 26 | ); 27 | 28 | BOOL __declspec(dllexport) WINAPI _createProcessW( 29 | _In_opt_ LPCWSTR lpApplicationName, 30 | _Inout_opt_ LPWSTR lpCommandLine, 31 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 32 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 33 | _In_ BOOL bInheritHandles, 34 | _In_ DWORD dwCreationFlags, 35 | _In_opt_ LPVOID lpEnvironment, 36 | _In_opt_ LPCWSTR lpCurrentDirectory, 37 | _In_ LPSTARTUPINFOW lpStartupInfo, 38 | _Out_ LPPROCESS_INFORMATION lpProcessInformation 39 | ); 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /BotMon/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | #include 4 | #include 5 | 6 | IMAGE_NT_HEADERS* get_nt_hrds(BYTE *pe_buffer) 7 | { 8 | if (pe_buffer == NULL) return NULL; 9 | 10 | IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER*)pe_buffer; 11 | if (idh->e_magic != IMAGE_DOS_SIGNATURE) { 12 | return NULL; 13 | } 14 | const LONG kMaxOffset = 1024; 15 | LONG pe_offset = idh->e_lfanew; 16 | if (pe_offset > kMaxOffset) return NULL; 17 | 18 | IMAGE_NT_HEADERS *inh = (IMAGE_NT_HEADERS *)((BYTE*)pe_buffer + pe_offset); 19 | return inh; 20 | } 21 | 22 | LPVOID search_pe_hdr(BYTE *buf, DWORD buf_size) 23 | { 24 | for (DWORD i = 0; i < buf_size; i++) { 25 | IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER*) buf; 26 | if (get_nt_hrds((BYTE*)idh) != NULL) return idh; 27 | buf++; 28 | } 29 | return NULL; 30 | } 31 | 32 | BOOL starts_with(LPVOID buffer, DWORD bufferSize, LPCSTR keyword) 33 | { 34 | const DWORD check_size = static_cast(strlen(keyword)); 35 | if (bufferSize < check_size) return FALSE; 36 | 37 | if (memcmp(buffer, keyword, check_size) == 0) { 38 | return TRUE; 39 | } 40 | return FALSE; 41 | } 42 | 43 | BOOL has_printable_line(LPVOID buffer, DWORD bufferSize) 44 | { 45 | if (bufferSize == 0) return FALSE; 46 | 47 | DWORD i = 0; 48 | for (; i < bufferSize; i++) { 49 | char c = ((char*)buffer)[i]; 50 | if (!isprint(c)) { 51 | if (i > 0 && (c == '\0' || c == '\n')) { 52 | return TRUE; 53 | } 54 | return FALSE; 55 | } 56 | } 57 | return TRUE; 58 | } 59 | 60 | size_t get_file_size(const char *filename) 61 | { 62 | FILE *fp = fopen(filename, "rb"); 63 | if (!fp) return 0; 64 | 65 | fseek(fp, 0, SEEK_END); 66 | long size = ftell(fp); 67 | fclose(fp); 68 | return size; 69 | } 70 | -------------------------------------------------------------------------------- /BotMon/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | LPVOID search_pe_hdr(BYTE *buf, DWORD buf_size); 6 | BOOL starts_with(LPVOID buffer, DWORD bufferSize, LPCSTR keyword); 7 | 8 | //counts printable characters, starting form the beginning till the first non-printable 9 | BOOL has_printable_line(LPVOID buffer, DWORD bufferSize); 10 | 11 | size_t get_file_size(const char *filename); 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project ( IAT_patcher_libs ) 3 | 4 | # modules: 5 | set ( M_BOT_MON "BotMon" ) 6 | set ( M_CH_COLORS "ChangeColors" ) 7 | 8 | # Add sub-directories 9 | # 10 | add_subdirectory( ${M_BOT_MON} ) 11 | add_subdirectory( ${M_CH_COLORS} ) 12 | -------------------------------------------------------------------------------- /ChangeColors/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (ChangeColors) 3 | 4 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") 5 | 6 | set (srcs 7 | main.cpp 8 | ) 9 | 10 | set (hdrs 11 | main.h 12 | ) 13 | 14 | add_library (ChangeColors SHARED ${hdrs} ${srcs} main.def) 15 | 16 | #install 17 | INSTALL( TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT ${PROJECT_NAME} ) 18 | -------------------------------------------------------------------------------- /ChangeColors/README.md: -------------------------------------------------------------------------------- 1 | ChangeColors - sample library for [IAT Patcher](http://hasherezade.github.io/IAT_patcher/) (C/C++) 2 | --- 3 | 4 | Purpose:
5 | - 6 | Changes default color set of the hooked application. 7 | 8 | Usage:
9 | -- 10 | Use IAT Patcher to hook your program.
11 | 12 | **Replace**: 13 | 14 | `GDI32.dll.SetTextColor` -> `MyLib.dll.MyTextColor` (changes text color to a random color)
15 | `USER32.dll.GetSysColor` -> `MyLib.dll.MySysColor` (applies color set defined in file: `colors.cfg`)
16 | -------------------------------------------------------------------------------- /ChangeColors/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include 3 | using namespace std; 4 | 5 | map g_IndexToColor; 6 | 7 | COLORREF __stdcall MyTextColor(HDC hdc, COLORREF crColor) 8 | { 9 | srand ((unsigned int)time(NULL)); 10 | DWORD colorBuf = rand(); 11 | 12 | return SetTextColor(hdc, colorBuf); 13 | } 14 | 15 | void readColors() 16 | { 17 | FILE *fp = fopen("colors.cfg", "r"); 18 | if (fp == NULL) return; 19 | 20 | const size_t strSize = 101; 21 | char mystring[strSize]; 22 | DWORD index = 0; 23 | DWORD color = 0; 24 | 25 | while (!feof(fp)) { 26 | 27 | if (fgets (mystring , strSize - 1 , fp) == NULL) continue; 28 | 29 | sscanf(mystring, "%d:%x", &index, &color); 30 | 31 | DWORD red = (color & 0xFF0000) >> 16; 32 | DWORD green = (color & 0x00FF00) >> 8; 33 | DWORD blue = (color & 0x0000FF); 34 | 35 | color = RGB(red, green, blue); 36 | g_IndexToColor[index] = color; 37 | } 38 | fclose(fp); 39 | return; 40 | } 41 | 42 | COLORREF __stdcall MySysColor(int nIndex) 43 | { 44 | if (g_IndexToColor.find(nIndex) != g_IndexToColor.end()) { 45 | return g_IndexToColor[nIndex]; 46 | } 47 | return GetSysColor(nIndex); 48 | } 49 | 50 | BOOL WINAPI DllMain (HANDLE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 51 | { 52 | switch (fdwReason) 53 | { 54 | case DLL_PROCESS_ATTACH: 55 | { 56 | readColors(); 57 | break; 58 | } 59 | case DLL_THREAD_ATTACH: 60 | case DLL_THREAD_DETACH: 61 | case DLL_PROCESS_DETACH: 62 | break; 63 | } 64 | 65 | return TRUE; 66 | } 67 | -------------------------------------------------------------------------------- /ChangeColors/main.def: -------------------------------------------------------------------------------- 1 | LIBRARY MyLib 2 | EXPORTS MyTextColor 3 | EXPORTS MySysColor 4 | -------------------------------------------------------------------------------- /ChangeColors/main.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern "C" { 6 | COLORREF __declspec(dllexport) __stdcall MyTextColor(HDC hdc, COLORREF crColor); 7 | }; 8 | -------------------------------------------------------------------------------- /ChangeColors/sample/colors.cfg: -------------------------------------------------------------------------------- 1 | 5:000000 2 | 8:00ff00 3 | 14:0000ff 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sample libraries for IAT Patcher
2 | === 3 | [![Build status](https://ci.appveyor.com/api/projects/status/boah2qwd7cp777hd?svg=true)](https://ci.appveyor.com/project/hasherezade/iat-patcher-samples) 4 | 5 | Usage:
6 | -- 7 | Use [IAT Patcher](https://github.com/hasherezade/IAT_patcher) to hook your program with the chosen library.
8 | 9 | Download: 10 | - 11 | Fresh builds can be downloaded from [the build server](https://ci.appveyor.com/project/hasherezade/iat-patcher-samples) (click on the build and choose the "Artifacts" tab) 12 | -------------------------------------------------------------------------------- /ShowProc/README.md: -------------------------------------------------------------------------------- 1 | ShowProc - sample library for IAT Patcher* (masm32/WinAsm) 2 | -- 3 | *https://github.com/hasherezade/IAT_patcher
4 | 5 | Purpose:
6 | - 7 | Prints list of dynamically loaded modules and functions.
8 | 9 | Output is saved in file: "ProcList.txt"
10 | Format:
11 |
12 | [return_address]; loaded [Name]
13 |
14 | Example:
15 | -- 16 |
17 | 19aa50; loaded: KERNEL32.DLL
18 | 19aa6e; loaded: SystemTimeToFileTime
19 | 19aa6e; loaded: SetEvent
20 | 
21 | Usage:
22 | -- 23 | Use IAT Patcher to hook your program.
24 | Replace:
25 | Kernel32.dll.GetModuleHandleA -> ShowProc.dll.PrintLibNameA
26 | Kernel32.dll.GetProcAddress -> ShowProc.dll.PrintProcName
27 | -------------------------------------------------------------------------------- /ShowProc/ShowProc.wap: -------------------------------------------------------------------------------- 1 | [PROJECT] 2 | Type=1 3 | ReleaseCommandLine= 4 | DebugCommandLine= 5 | AutoIncFileVersion=0 6 | RCSilent=0 7 | PellesTools=0 8 | [MAKE] 9 | ActiveBuild=0 10 | CompileRC=/v 11 | RCToObj= 12 | Assemble=/c /coff /Cp /nologo 13 | Link=/SUBSYSTEM:WINDOWS /RELEASE /VERSION:4.0 14 | Out= 15 | DebAssemble=/Zi /Zd /c /coff /Cp /nologo 16 | DebLink=/SUBSYSTEM:WINDOWS /DEBUG /DEBUGTYPE:CV /VERSION:4.0 /INCREMENTAL:NO 17 | DebOut= 18 | [FILES] 19 | 1=main.asm 20 | 2=main.def 21 | [SHOWFILE] 22 | 1=00000000000000009C0500008502000000000000030000004700000072 23 | 2=0D0000005B000000A9050000E0020000010000000100000000000000FA 24 | -------------------------------------------------------------------------------- /ShowProc/main.asm: -------------------------------------------------------------------------------- 1 | ; CC-BY: hasherezade 2 | ; Sample library for IAT Patcher 3 | 4 | .386 5 | .model flat,stdcall 6 | option casemap:none 7 | 8 | include windows.inc 9 | 10 | include kernel32.inc 11 | include msvcrt.inc 12 | 13 | IncludeLib kernel32.lib 14 | includelib msvcrt.lib 15 | 16 | .data 17 | szFileFmt db 'w',0 18 | szFileName db 'ProcList.txt',0 19 | 20 | szFmtS db '%x; loaded: %s', 0ah, 0dh,0 21 | szFmtOrd db '%x; loaded: ', 0ah, 0dh,0 22 | 23 | .data? 24 | hFile HANDLE ? 25 | dwAddr HANDLE ? 26 | 27 | ASSUME FS:NOTHING 28 | 29 | .code 30 | DllEntry proc hInstance:HINSTANCE, reason:DWORD, reserved1:DWORD 31 | .if reason==DLL_PROCESS_ATTACH 32 | 33 | ;create the file 34 | invoke crt_fopen,offset szFileName, offset szFileFmt 35 | mov hFile,eax 36 | 37 | .elseif reason==DLL_PROCESS_DETACH 38 | invoke crt_fclose,hFile 39 | mov hFile, 0 40 | .endif 41 | ret 42 | DllEntry Endp 43 | 44 | 45 | strlen proc string:PSTR 46 | push edx 47 | xor eax,eax 48 | 49 | mov edx, dword ptr[string] 50 | test edx, 0FFFF0000h ; by ordinal? (or NULL) 51 | je _strlen_end 52 | 53 | mov edx, dword ptr[string] 54 | _is_null: 55 | 56 | cmp byte ptr[edx+eax],0 57 | je _strlen_end 58 | 59 | ;printable? 60 | cmp byte ptr[edx+eax],20h 61 | jl _strlen_end 62 | cmp byte ptr[edx+eax],7Fh 63 | jg _strlen_end 64 | 65 | inc eax 66 | jmp _is_null 67 | _strlen_end: 68 | pop edx 69 | ret 70 | strlen endp 71 | 72 | 73 | print_to_file proc lpString:LPCSTR 74 | mov eax, hFile 75 | cmp eax, 0 76 | je _print_end 77 | 78 | invoke strlen,lpString 79 | cmp eax, 0 80 | je _print_ord 81 | 82 | ;invoke crt_printf, addr szFmtS, dwAddr, lpString 83 | invoke crt_fprintf, hFile, addr szFmtS,dwAddr, lpString 84 | jmp _flush_file 85 | 86 | _print_ord: 87 | ;invoke crt_printf, addr szFmtOrd,dwAddr, lpString 88 | invoke crt_fprintf, hFile, addr szFmtOrd,dwAddr, lpString 89 | 90 | _flush_file: 91 | invoke crt_fflush, hFile 92 | 93 | _print_end: 94 | Ret 95 | print_to_file EndP 96 | 97 | va_to_rva proc dwVA:HANDLE 98 | push edx 99 | mov eax, dwVA 100 | 101 | mov edx, dword ptr fs:[30h] 102 | mov edx, [edx+8] 103 | sub eax, edx 104 | 105 | pop edx 106 | Ret 107 | va_to_rva EndP 108 | 109 | PrintProcName proc hModule:HMODULE, lpName:LPCSTR 110 | 111 | ; save return RVA: 112 | mov eax, dword ptr [ebp+4] 113 | invoke va_to_rva, eax 114 | mov dwAddr, eax 115 | 116 | invoke print_to_file,lpName 117 | 118 | invoke_origina1: 119 | invoke GetProcAddress,hModule,lpName 120 | Ret 121 | PrintProcName EndP 122 | 123 | PrintLibNameA proc lpLibName:LPCSTR 124 | 125 | ; save return RVA: 126 | mov eax, dword ptr [ebp+4] 127 | invoke va_to_rva, eax 128 | mov dwAddr, eax 129 | 130 | invoke print_to_file,lpLibName 131 | 132 | invoke_original2: 133 | invoke LoadLibrary,lpLibName 134 | Ret 135 | PrintLibNameA EndP 136 | 137 | End DllEntry 138 | -------------------------------------------------------------------------------- /ShowProc/main.def: -------------------------------------------------------------------------------- 1 | LIBRARY ShowProc 2 | EXPORTS PrintProcName 3 | EXPORTS PrintLibNameA 4 | --------------------------------------------------------------------------------