🤬
  • ■ ■ ■ ■ ■ ■
    SearchAvailableExe/CmdlineParser.hpp
     1 +#include <windows.h>
     2 +#include <stdint.h>
     3 +#include <stdio.h>
     4 + 
     5 +#define OPT_MAX_STRING 256
     6 + 
     7 +#define OPT_TYPE_NONE 1
     8 +#define OPT_TYPE_STRING 2
     9 +#define OPT_TYPE_DEC 3
     10 +#define OPT_TYPE_HEX 4
     11 +#define OPT_TYPE_FLAG 5
     12 +#define OPT_TYPE_DEC64 6
     13 +#define OPT_TYPE_HEX64 7
     14 + 
     15 +// structure to hold data of any type
     16 +typedef union _opt_arg_t {
     17 + int flag;
     18 + 
     19 + int8_t s8;
     20 + uint8_t u8;
     21 + int8_t* s8_ptr;
     22 + uint8_t* u8_ptr;
     23 + 
     24 + int16_t s16;
     25 + uint16_t u16;
     26 + int16_t* s16_ptr;
     27 + uint16_t* u16_ptr;
     28 + 
     29 + int32_t s32;
     30 + uint32_t u32;
     31 + int32_t* s32_ptr;
     32 + uint32_t* u32_ptr;
     33 + 
     34 + int64_t s64;
     35 + uint64_t u64;
     36 + int64_t* s64_ptr;
     37 + uint64_t* u64_ptr;
     38 + 
     39 + void* ptr;
     40 + char str[OPT_MAX_STRING + 1];
     41 +} opt_arg;
     42 + 
     43 +typedef int (*void_callback_t)(void); // execute callback with no return value or argument
     44 +typedef int (*arg_callback_t)(opt_arg*, void*); // process argument, optionally store in optarg
     45 + 
     46 +static int get_opt(
     47 + int argc, // total number of elements in argv
     48 + char* argv[], // argument array
     49 + int arg_type, // type of argument expected (none, flag, decimal, hexadecimal, string)
     50 + void* output, // pointer to variable that stores argument
     51 + char* short_opt, // short form of option. e.g: -a
     52 + char* long_opt, // long form of option. e.g: --arch
     53 + void* callback) // callback function to process argument
     54 +{
     55 + int valid = 0, i, req = 0, opt_len, opt_type;
     56 + char* args = NULL, * opt = NULL, * arg = NULL, * tmp = NULL;
     57 + opt_arg* optarg = (opt_arg*)output;
     58 + void_callback_t void_cb;
     59 + arg_callback_t arg_cb;
     60 + 
     61 + // perform some basic validation
     62 + if (argc <= 1) return 0;
     63 + if (argv == NULL) return 0;
     64 + 
     65 + if (arg_type != OPT_TYPE_NONE &&
     66 + arg_type != OPT_TYPE_STRING &&
     67 + arg_type != OPT_TYPE_DEC &&
     68 + arg_type != OPT_TYPE_HEX &&
     69 + arg_type != OPT_TYPE_HEX64 &&
     70 + arg_type != OPT_TYPE_FLAG) return 0;
     71 + 
     72 + /*printf("Arg type for %s, %s : %s",
     73 + short_opt != NULL ? short_opt : "N/A",
     74 + long_opt != NULL ? long_opt : "N/A",
     75 + arg_type == OPT_TYPE_NONE ? "None" :
     76 + arg_type == OPT_TYPE_STRING ? "String" :
     77 + arg_type == OPT_TYPE_DEC ? "Decimal" :
     78 + arg_type == OPT_TYPE_HEX ? "Hexadecimal" :
     79 + arg_type == OPT_TYPE_FLAG ? "Flag" : "Unknown");*/
     80 + 
     81 + // for each argument in array
     82 + for (i = 1; i < argc && !valid; i++) {
     83 + // set the current argument to examine
     84 + arg = argv[i];
     85 + // if it doesn't contain a switch, skip it
     86 + if (*arg != '-') continue;
     87 + // we have a switch. initially, we assume short form
     88 + arg++;
     89 + opt_type = 0;
     90 + // long form? skip one more and change the option type
     91 + if (*arg == '-') {
     92 + arg++;
     93 + opt_type++;
     94 + }
     95 + 
     96 + // is an argument required by the user?
     97 + req = ((arg_type != OPT_TYPE_NONE) && (arg_type != OPT_TYPE_FLAG));
     98 + // use short or long form for current argument being examined
     99 + opt = (opt_type) ? long_opt : short_opt;
     100 + // if no form provided by user for current argument, skip it
     101 + if (opt == NULL) continue;
     102 + // copy string to dynamic buffer
     103 + opt_len = strlen(opt);
     104 + if (opt_len == 0) continue;
     105 + 
     106 + tmp = (char*)calloc(sizeof(uint8_t), opt_len + 1);
     107 + if (tmp == NULL) {
     108 + //printf("Unable to allocate memory for %s.\n", opt);
     109 + continue;
     110 + }
     111 + else {
     112 + strcpy(tmp, opt);
     113 + }
     114 + // tokenize the string.
     115 + opt = strtok(tmp, ";");
     116 + // while we have options
     117 + while (opt != NULL && !valid) {
     118 + // get the length
     119 + opt_len = strlen(opt);
     120 + // do we have a match?
     121 + if (!strncmp(opt, arg, opt_len)) {
     122 + //
     123 + // at this point, we have a valid matching argument
     124 + // if something fails from here on in, return invalid
     125 + //
     126 + // skip the option
     127 + arg += opt_len;
     128 + // an argument is *not* required
     129 + if (!req) {
     130 + // so is the next byte non-zero? return invalid
     131 + if (*arg != 0) return 0;
     132 + }
     133 + else {
     134 + // an argument is required
     135 + // if the next byte is a colon or assignment operator, skip it.
     136 + if (*arg == ':' || *arg == '=') arg++;
     137 + 
     138 + // if the next byte is zero
     139 + if (*arg == 0) {
     140 + // and no arguments left. return invalid
     141 + if ((i + 1) >= argc) return 0;
     142 + args = argv[i + 1];
     143 + }
     144 + else {
     145 + args = arg;
     146 + }
     147 + }
     148 + // end loop
     149 + valid = 1;
     150 + break;
     151 + }
     152 + opt = strtok(NULL, ";");
     153 + }
     154 + if (tmp != NULL) free(tmp);
     155 + }
     156 + 
     157 + // if valid option found
     158 + if (valid) {
     159 + //printf("Found match");
     160 + // ..and a callback exists
     161 + if (callback != NULL) {
     162 + // if we have a parameter
     163 + if (args != NULL) {
     164 + //printf("Executing callback with %s.", args);
     165 + // execute with parameter
     166 + arg_cb = (arg_callback_t)callback;
     167 + int result = arg_cb(optarg, args);
     168 + if (result == 0) {
     169 + printf("-%s parameter Parsing Error!", short_opt);
     170 + exit(0);
     171 + }
     172 + }
     173 + else {
     174 + //printf("Executing callback.");
     175 + // otherwise, execute without
     176 + void_cb = (void_callback_t)callback;
     177 + int result = void_cb();
     178 + if (result == 0) {
     179 + printf("-%s parameter Parsing Error!", short_opt);
     180 + exit(0);
     181 + }
     182 + }
     183 + }
     184 + else {
     185 + // there's no callback, try process ourselves
     186 + if (args != NULL) {
     187 + //printf("Parsing %s\n", args);
     188 + switch (arg_type) {
     189 + case OPT_TYPE_DEC:
     190 + case OPT_TYPE_HEX:
     191 + //printf("Converting %s to 32-bit binary", args);
     192 + optarg->u32 = strtoul(args, NULL, arg_type == OPT_TYPE_DEC ? 10 : 16);
     193 + break;
     194 + case OPT_TYPE_DEC64:
     195 + case OPT_TYPE_HEX64:
     196 + //printf("Converting %s to 64-bit binary", args);
     197 + optarg->u64 = strtoull(args, NULL, arg_type == OPT_TYPE_DEC64 ? 10 : 16);
     198 + break;
     199 + case OPT_TYPE_STRING:
     200 + //printf("Copying %s to output", args);
     201 + strncpy(optarg->str, args, OPT_MAX_STRING);
     202 + break;
     203 + }
     204 + }
     205 + else {
     206 + // there's no argument, just set the flag
     207 + //printf("Setting flag");
     208 + optarg->flag = 1;
     209 + }
     210 + }
     211 + }
     212 + // return result
     213 + return valid;
     214 +}
  • ■ ■ ■ ■ ■
    SearchAvailableExe/SearchAvailableExe.cpp
    1  -#include <iostream>
    2  -#include <windows.h>
    3  -#include <fstream>
    4  -#include <thread>
     1 +#include <thread>
    5 2  #include "Tools.h"
     3 +#include "CmdlineParser.hpp"
    6 4   
    7 5  using namespace std;
    8 6   
    9 7  vector<PResultInfo> results;
     8 +ARG_CONFIG c;
    10 9   
    11 10  void ThreadFunction(const std::wstring& filePath) {
    12 11   VerifyFileSignature(filePath.c_str());
    skipped 30 lines
    43 42   }
    44 43  }
    45 44   
    46  -int main() {
    47  - string outputFilename = "output.txt";
    48  - ofstream outputFile(outputFilename);
     45 +bool compare(PResultInfo a, PResultInfo b) {
     46 + int aPreSize = a->preLoadDlls.size() == 0 ? 999 : a->preLoadDlls.size();
     47 + int aPostSize = a->postLoadDlls.size() == 0 ? 999 : a->postLoadDlls.size();
     48 + int bPreSize = b->preLoadDlls.size() == 0 ? 999 : b->preLoadDlls.size();
     49 + int bPostSize = b->postLoadDlls.size() == 0 ? 999 : b->postLoadDlls.size();
    49 50   
    50  - if (!outputFile.is_open()) {
    51  - cerr << "Failed to open output file." << endl;
     51 + if ((aPreSize < bPreSize && aPreSize < bPostSize) || (aPostSize < bPreSize && aPostSize < bPostSize))
     52 + return true;
     53 + else if ((bPreSize < aPreSize && bPreSize < aPostSize) || (bPostSize < aPreSize && bPostSize < aPostSize))
     54 + return false;
     55 + else {
     56 + return a->isWrite > b->isWrite;
     57 + }
     58 +}
     59 + 
     60 +bool isUnwanted(const PResultInfo result) {
     61 + if (c.isWrite == 1 && result->isWrite == 0)
     62 + return true;
     63 + if ((c.bit == 32 && result->bit != 32) || (c.bit == 64 && result->bit != 64))
     64 + return true;
     65 + if (c.dllCount < result->postLoadDlls.size() && c.dllCount < result->preLoadDlls.size())
     66 + return true;
     67 + 
     68 + return false;
     69 +}
     70 + 
     71 +static int validate_dllCount(opt_arg* arg, void* args) {
     72 + char* str = (char*)args;
     73 + 
     74 + arg->u32 = 0;
     75 + if (str == NULL) return 0;
     76 + 
     77 + arg->u32 = atoi(str);
     78 + 
     79 + if (arg->u32 <= 0)
     80 + return 0;
     81 + else
    52 82   return 1;
     83 +}
     84 + 
     85 +static int validate_bit(opt_arg* arg, void* args) {
     86 + char* str = (char*)args;
     87 + 
     88 + arg->u32 = 0;
     89 + if (str == NULL) return 0;
     90 + 
     91 + arg->u32 = atoi(str);
     92 + 
     93 + if (arg->u32 != 32 && arg->u32 != 64 && arg->u32 != 96)
     94 + return 0;
     95 + else
     96 + return 1;
     97 +}
     98 + 
     99 +static void usage(void) {
     100 + printf("usage: SearchAvailableExe [options]\n");
     101 + printf(" -o,--output: <path> Output file to save dll info. Default is output command.\n");
     102 + printf(" -i,--input: <path> Input search path. Default traverse all disks.\n");
     103 + printf(" -w,--write: <bool> Whether to only output information about directories with write permissions, with the default value being 'no'.\n");
     104 + printf(" -c,--count: <count> Controls the output of the number of DLLs loaded by white programs, only outputting if the count is less than or equal to a specified value. The default value is 5.\n");
     105 + printf(" -b,--bit: <count> Select the output bitness, supporting 32, 64, and 96 bits. The default is 96 bits, while also outputting information for 32 and 64-bit white programs.\n");
     106 + exit(0);
     107 +}
     108 + 
     109 +int main(int argc, char* argv[]) {
     110 +
     111 + memset(&c, 0, sizeof(c));
     112 +
     113 + c.dllCount = 5;
     114 + c.bit = 96;
     115 + 
     116 + get_opt(argc, argv, OPT_TYPE_NONE, NULL, "h;?", "help", usage);
     117 + get_opt(argc, argv, OPT_TYPE_STRING, c.output, "o", "output", NULL);
     118 + get_opt(argc, argv, OPT_TYPE_STRING, c.input, "i", "input", NULL);
     119 + get_opt(argc, argv, OPT_TYPE_FLAG, &c.isWrite, "w", "write", NULL);
     120 + get_opt(argc, argv, OPT_TYPE_DEC, &c.dllCount, "c", "count", validate_dllCount);
     121 + get_opt(argc, argv, OPT_TYPE_DEC, &c.bit, "b", "bit", validate_bit);
     122 + 
     123 + ostream* output = &cout;
     124 + ofstream outputFile;
     125 + if (c.output[0] != 0) {
     126 + outputFile.open(c.output);
     127 + 
     128 + if (!outputFile.is_open()) {
     129 + cerr << "Failed to open output file." << endl;
     130 + return 1;
     131 + }
     132 + output = &outputFile;
    53 133   }
    54 134   
    55  - // 遍历系统的所有盘符
    56  - for (char drive = 'A'; drive <= 'Z'; ++drive) {
    57  - wstring rootDirectory = wstring(1, drive) + L":";
    58  - ListExecutableFiles(rootDirectory);
     135 + if (c.input[0] == 0) {
     136 + for (char drive = 'A'; drive <= 'Z'; ++drive) {
     137 + wstring rootDirectory = wstring(1, drive) + L":";
     138 + ListExecutableFiles(rootDirectory);
     139 + }
     140 + }
     141 + else {
     142 + ListExecutableFiles(ConvertToWideString(c.input));
    59 143   }
    60 144   
    61  - //wstring rootDirectory = L"D:\\Code\\TeamWorkspace\\beacon\\白+黑 嵌入生成";
    62  - //wstring rootDirectory = L"C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Tools\\Llvm\\x64\\bin";
    63  - /*wstring rootDirectory = L"D:\\Users\\MaoKu\\AppData\\Local\\Programs\\Microsoft VS Code\\bin";
    64  - ListExecutableFiles(rootDirectory);*/
     145 + sort(results.begin(), results.end(), compare);
     146 + 
     147 + results.erase(std::remove_if(results.begin(), results.end(), isUnwanted), results.end());
    65 148   
    66 149   for (const auto& result : results) {
    67  - outputFile << result->filePath << endl;
    68  - outputFile << "程序位数: " << result->bit << " 目录是否可写: " << result->isWrite << endl;
     150 + *output << result->filePath << endl;
     151 + *output << "程序位数: " << result->bit << " 目录是否可写: " << result->isWrite << endl;
    69 152   
    70 153   if (result->preLoadDlls.size() > 0) {
    71  - outputFile << "预加载DLL个数: " << result->preLoadDlls.size() << endl;
     154 + *output << "预加载DLL个数: " << result->preLoadDlls.size() << endl;
    72 155   for (const auto& dll : result->preLoadDlls) {
    73  - outputFile << dll << endl;
     156 + *output << dll << endl;
    74 157   delete[] dll;
    75 158   }
    76 159   }
    77 160   
    78 161   if (result->postLoadDlls.size() > 0) {
    79  - outputFile << "动态加载DLL个数: " << result->postLoadDlls.size() << endl;
     162 + *output << "动态加载DLL个数: " << result->postLoadDlls.size() << endl;
    80 163   for (const auto& dll : result->postLoadDlls) {
    81  - outputFile << dll << endl;
     164 + *output << dll << endl;
    82 165   delete[] dll;
    83 166   }
    84 167   }
    85 168   
    86  - outputFile << "-------------------------" << endl;
     169 + *output << "--------------------------------------------------" << endl;
    87 170   
    88 171   delete result;
    89 172   }
    90 173   
    91  - outputFile.close();
    92  - cout << "Output saved to " << outputFilename << endl;
     174 + if (c.output[0] != 0) {
     175 + outputFile.close();
     176 + cout << "Search finish. Output saved to " << c.output << endl;
     177 + }
     178 + else
     179 + cout << "Search finish!" << endl;
    93 180   
    94 181   return 0;
    95 182  }
  • ■ ■ ■ ■ ■ ■
    SearchAvailableExe/SearchAvailableExe.vcxproj
    skipped 36 lines
    37 37   <UseDebugLibraries>false</UseDebugLibraries>
    38 38   <PlatformToolset>v143</PlatformToolset>
    39 39   <WholeProgramOptimization>true</WholeProgramOptimization>
    40  - <CharacterSet>MultiByte</CharacterSet>
     40 + <CharacterSet>Unicode</CharacterSet>
    41 41   </PropertyGroup>
    42 42   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    43 43   <ConfigurationType>Application</ConfigurationType>
    skipped 31 lines
    75 75   <WarningLevel>Level3</WarningLevel>
    76 76   <SDLCheck>true</SDLCheck>
    77 77   <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    78  - <ConformanceMode>true</ConformanceMode>
     78 + <ConformanceMode>false</ConformanceMode>
    79 79   <LanguageStandard>stdcpp17</LanguageStandard>
    80 80   </ClCompile>
    81 81   <Link>
    skipped 9 lines
    91 91   <IntrinsicFunctions>true</IntrinsicFunctions>
    92 92   <SDLCheck>true</SDLCheck>
    93 93   <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    94  - <ConformanceMode>true</ConformanceMode>
    95  - <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
     94 + <ConformanceMode>false</ConformanceMode>
     95 + <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
     96 + <LanguageStandard>stdcpp17</LanguageStandard>
    96 97   </ClCompile>
    97 98   <Link>
    98 99   <SubSystem>Console</SubSystem>
    skipped 36 lines
    135 136   <ClCompile Include="Tools.cpp" />
    136 137   </ItemGroup>
    137 138   <ItemGroup>
     139 + <ClInclude Include="CmdlineParser.hpp" />
    138 140   <ClInclude Include="Tools.h" />
    139 141   </ItemGroup>
    140 142   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    skipped 3 lines
  • ■ ■ ■ ■ ■ ■
    SearchAvailableExe/SearchAvailableExe.vcxproj.filters
    skipped 25 lines
    26 26   <ClInclude Include="Tools.h">
    27 27   <Filter>头文件</Filter>
    28 28   </ClInclude>
     29 + <ClInclude Include="CmdlineParser.hpp">
     30 + <Filter>源文件</Filter>
     31 + </ClInclude>
    29 32   </ItemGroup>
    30 33  </Project>
  • ■ ■ ■ ■
    SearchAvailableExe/SearchAvailableExe.vcxproj.user
    1 1  <?xml version="1.0" encoding="utf-8"?>
    2 2  <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    3  - <PropertyGroup />
     3 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     4 + <LocalDebuggerCommandArguments>-i "D:\Code\TeamWorkspace\beacon\白+黑 嵌入生成"</LocalDebuggerCommandArguments>
     5 + <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
     6 + </PropertyGroup>
    4 7  </Project>
  • ■ ■ ■ ■ ■ ■
    SearchAvailableExe/Tools.cpp
    skipped 154 lines
    155 155   DWORD rdataLength;
    156 156   BYTE* rdata = readRDataSection(buffer, &rdataLength);
    157 157   if (rdata != 0) {
    158  - char fileFullPath[255] = { 0 };
     158 + char fileFullPath[0x255] = { 0 };
    159 159   strcat(fileFullPath, fileDir.c_str());
    160 160   int fileDirLength = fileDir.length();
    161 161   DWORD vaule, vaule1;
    skipped 28 lines
    190 190   str = ConvertWideToMultiByte((wchar_t*)(rdata + i + 2));
    191 191   
    192 192   strLength = strlen(str);
    193  - if (strLength > 35);
     193 + if (str[strLength-1] != 'l')
    194 194   continue;
    195 195   
    196 196   memcpy(fileFullPath + fileDirLength, str, strLength + 1);
    skipped 67 lines
    264 264   while (ImportTable->Name)
    265 265   {
    266 266   char* pName = (char*)(rvaToFOA(buffer, ImportTable->Name) + buffer);
    267  - DWORD nameSize = sizeof(known_dlls) / 4;
    268  - bool flag = true;
    269  -
    270  - for (int i = 0; i < nameSize; i++)
    271  - {
    272  - if (containsIgnoreCase(pName, known_dlls[i]) != NULL)
    273  - {
    274  - flag = false;
    275  - break;
    276  - }
    277  - }
    278 267   
    279 268   PIMAGE_THUNK_DATA INT = PIMAGE_THUNK_DATA(rvaToFOA(buffer, ImportTable->OriginalFirstThunk) + buffer);
    280  - PIMAGE_THUNK_DATA IAT = PIMAGE_THUNK_DATA(rvaToFOA(buffer, ImportTable->FirstThunk) + buffer);
    281 269   PIMAGE_IMPORT_BY_NAME temp = { 0 };
    282 270   int count = 0;
    283 271   while (INT->u1.AddressOfData)//当遍历到的是最后一个是时候是会为0,所以随便遍历一个就好
    skipped 16 lines
    300 288   strcat(fileFullPath, pName);
    301 289   
    302 290   if (filesystem::exists(filesystem::path(fileFullPath)))
    303  - flag = true;
    304  -
    305  - if (flag)
    306 291   result->preLoadDlls.push_back(_strdup(pName));
    307 292   
    308 293   ImportTable++;
    skipped 59 lines
    368 353   return FALSE;
    369 354   }
    370 355   
    371  - /*string md5 = calculateMD5(pbFile, dwFileSize);
     356 + /* string md5 = calculateMD5(pbFile, dwFileSize);
    372 357   {
    373 358   std::lock_guard<std::mutex> lock(mtx);
    374 359   if (md5Map.find(md5) != md5Map.end())
    skipped 24 lines
    399 384   
    400 385   return TRUE;
    401 386  }
     387 + 
     388 +std::wstring ConvertToWideString(const char* input) {
     389 + int length = strlen(input) + 1;
     390 + int requiredLength = MultiByteToWideChar(CP_ACP, 0, input, length, NULL, 0);
     391 + wchar_t* buffer = new wchar_t[requiredLength];
     392 + MultiByteToWideChar(CP_ACP, 0, input, length, buffer, requiredLength);
     393 + std::wstring result(buffer);
     394 + delete[] buffer;
     395 + return result;
     396 +}
  • ■ ■ ■ ■ ■ ■
    SearchAvailableExe/Tools.h
    skipped 19 lines
    20 20   vector<char*> postLoadDlls;
    21 21  } ResultInfo, * PResultInfo;
    22 22   
     23 +#define STRING_MAX 256
     24 +typedef struct {
     25 + char input[STRING_MAX];
     26 + char output[STRING_MAX];
     27 + bool isWrite;
     28 + int dllCount;
     29 + int bit;
     30 +} ARG_CONFIG, * PARG_CONFIG;
     31 + 
    23 32  BOOL VerifyFileSignature(LPCWSTR filePath);
     33 +std::wstring ConvertToWideString(const char* input);
    24 34   
Please wait...
Page is in error, reload to recover