1 1 #include "Tools.h" 2 2 3 3 extern vector<PResultInfo> results; 4 - std::unordered_map<std::string, std::wstring> md5Map; 4 + extern ARG_CONFIG c; 5 5 std::mutex mtx; 6 6 7 - std::string calculateMD5(BYTE* buffer, DWORD bytesRead) { 8 - std::string md5; 9 - 10 - // 初始化加密API 11 - HCRYPTPROV hProv = 0; 12 - if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 13 - std::cerr << "CryptAcquireContext failed\n"; 14 - return md5; 15 - } 16 - 17 - HCRYPTHASH hHash = 0; 18 - if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { 19 - std::cerr << "CryptCreateHash failed\n"; 20 - CryptReleaseContext(hProv, 0); 21 - return md5; 22 - } 23 - 24 - // 读取文件并更新哈希值 25 - if (!CryptHashData(hHash, buffer, bytesRead, 0)) { 26 - std::cerr << "CryptHashData failed\n"; 27 - CryptDestroyHash(hHash); 28 - CryptReleaseContext(hProv, 0); 29 - return md5; 30 - } 31 - 32 - // 获取哈希值 33 - DWORD hashSize = 16; // MD5 哈希值大小为 16 字节 34 - BYTE hashBuffer[16]; 35 - if (CryptGetHashParam(hHash, HP_HASHVAL, hashBuffer, &hashSize, 0)) { 36 - std::stringstream ss; 37 - ss << std::hex << std::setfill('0'); 38 - for (int i = 0; i < hashSize; ++i) { 39 - ss << std::setw(2) << static_cast<unsigned int>(hashBuffer[i]); 40 - } 41 - md5 = ss.str(); 42 - } 43 - else { 44 - std::cerr << "CryptGetHashParam failed\n"; 45 - } 46 - 47 - CryptDestroyHash(hHash); 48 - CryptReleaseContext(hProv, 0); 49 - 50 - return md5; 51 - } 52 - 53 7 string wstring2string(wstring wstr) 54 8 { 55 9 string result; skipped 165 lines 221 175 { 222 176 const char* known_dlls[] = {"kernel32", "wow64cpu", "wowarmhw", "xtajit", "advapi32", "clbcatq", "combase", "COMDLG32", "coml2", "difxapi", "gdi32", "gdiplus", "IMAGEHLP", "IMM32", "MSCTF", "MSVCRT", "NORMALIZ", "NSI", "ole32", "OLEAUT32", "PSAPI", "rpcrt4", "sechost", "Setupapi", "SHCORE", "SHELL32", "SHLWAPI", "user32", "WLDAP32", "wow64cpu", "wow64", "wow64base", "wow64con", "wow64win", "WS2_32", "xtajit64"}; 223 177 string fileDir = GetDirectoryFromPath(ConvertWideToMultiByte(filePath)) + "\\"; 178 + result->fileDir = fileDir; 224 179 225 180 if (hasWritePermission(fileDir)) 226 181 result->isWrite = true; skipped 126 lines 353 308 return FALSE; 354 309 } 355 310 356 - /* string md5 = calculateMD5(pbFile, dwFileSize); 357 - { 358 - std::lock_guard<std::mutex> lock(mtx); 359 - if (md5Map.find(md5) != md5Map.end()) 360 - return FALSE; 361 - 362 - md5Map[md5] = filePath; 363 - }*/ 364 - 365 311 ResultInfo* result = new ResultInfo; 366 312 result->filePath = wstring2string(filePath); 367 313 skipped 17 lines 385 331 return TRUE; 386 332 } 387 333 334 + int readFileContext(string path, char** contexts) 335 + { 336 + ifstream inFile(path, std::ios::binary); 337 + if (!inFile) { 338 + printf("%s open fail\n", path.c_str()); 339 + return -1; 340 + } 341 + 342 + inFile.seekg(0, std::ios::end); 343 + std::streamsize payloadFileSize = inFile.tellg(); 344 + inFile.seekg(0, std::ios::beg); 345 + 346 + *contexts = new char[payloadFileSize]; 347 + 348 + if (!inFile.read(*contexts, payloadFileSize)) { 349 + printf("%s payloadBuffer read fail\n", path.c_str()); 350 + delete[] contexts; 351 + return -1; 352 + } 353 + 354 + inFile.close(); 355 + 356 + return payloadFileSize; 357 + } 358 + 359 + void saveFile(string filePath, char* buffer, DWORD fileSize) 360 + { 361 + std::ofstream outFile; 362 + outFile.open(filePath, std::ios::binary | std::ios::trunc); 363 + outFile.write(buffer, fileSize); 364 + outFile.close(); 365 + } 366 + 367 + int fixExportTable(string targetFilePath, string sourceFilePath) 368 + { 369 + char* targetBuffer; 370 + DWORD fileSize = readFileContext(targetFilePath, &targetBuffer); 371 + 372 + PIMAGE_DOS_HEADER pDH = (PIMAGE_DOS_HEADER)targetBuffer; 373 + PIMAGE_NT_HEADERS pNtH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew); 374 + PIMAGE_OPTIONAL_HEADER pOH = &pNtH->OptionalHeader; 375 + IMAGE_DATA_DIRECTORY exportDirectory; 376 + 377 + if (*(PWORD)((size_t)pDH + pDH->e_lfanew + 0x18) == IMAGE_NT_OPTIONAL_HDR32_MAGIC) 378 + { 379 + PIMAGE_NT_HEADERS32 pNtH32 = PIMAGE_NT_HEADERS32((size_t)pDH + pDH->e_lfanew); 380 + PIMAGE_OPTIONAL_HEADER32 pOH32 = &pNtH32->OptionalHeader; 381 + 382 + exportDirectory = pOH32->DataDirectory[0]; 383 + } 384 + else { 385 + PIMAGE_NT_HEADERS64 pNtH64 = PIMAGE_NT_HEADERS64((size_t)pDH + pDH->e_lfanew); 386 + PIMAGE_OPTIONAL_HEADER64 pOH64 = &pNtH64->OptionalHeader; 387 + 388 + exportDirectory = pOH64->DataDirectory[0]; 389 + } 390 + 391 + IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)(targetBuffer + rvaToFOA(targetBuffer, exportDirectory.VirtualAddress)); 392 + 393 + DWORD* nameRVAs = (DWORD*)(targetBuffer + rvaToFOA(targetBuffer, exportDir->AddressOfNames)); 394 + 395 + char* sourceBuffer; 396 + readFileContext(sourceFilePath, &sourceBuffer); 397 + 398 + pDH = (PIMAGE_DOS_HEADER)sourceBuffer; 399 + pNtH = (PIMAGE_NT_HEADERS)((DWORD)pDH + pDH->e_lfanew); 400 + pOH = &pNtH->OptionalHeader; 401 + 402 + if (*(PWORD)((size_t)pDH + pDH->e_lfanew + 0x18) == IMAGE_NT_OPTIONAL_HDR32_MAGIC) 403 + { 404 + PIMAGE_NT_HEADERS32 pNtH32 = PIMAGE_NT_HEADERS32((size_t)pDH + pDH->e_lfanew); 405 + PIMAGE_OPTIONAL_HEADER32 pOH32 = &pNtH32->OptionalHeader; 406 + 407 + exportDirectory = pOH32->DataDirectory[0]; 408 + } 409 + else { 410 + PIMAGE_NT_HEADERS64 pNtH64 = PIMAGE_NT_HEADERS64((size_t)pDH + pDH->e_lfanew); 411 + PIMAGE_OPTIONAL_HEADER64 pOH64 = &pNtH64->OptionalHeader; 412 + 413 + exportDirectory = pOH64->DataDirectory[0]; 414 + } 415 + 416 + IMAGE_EXPORT_DIRECTORY* exportDir_source = (IMAGE_EXPORT_DIRECTORY*)(sourceBuffer + rvaToFOA(sourceBuffer, exportDirectory.VirtualAddress)); 417 + 418 + DWORD* nameRVAs_source = (DWORD*)(sourceBuffer + rvaToFOA(sourceBuffer, exportDir_source->AddressOfNames)); 419 + 420 + for (int i = 0; i < exportDir_source->NumberOfNames; i++) 421 + { 422 + DWORD nameRVA_source = nameRVAs_source[i]; 423 + char* exportFunctionName_source = sourceBuffer + rvaToFOA(sourceBuffer, nameRVA_source); 424 + 425 + DWORD nameRVA = nameRVAs[i]; 426 + char* exportFunctionName = targetBuffer + rvaToFOA(targetBuffer, nameRVA); 427 + 428 + memcpy(exportFunctionName, exportFunctionName_source, strlen(exportFunctionName_source)+1); 429 + } 430 + 431 + saveFile(targetFilePath, targetBuffer, fileSize); 432 + 433 + delete[] targetBuffer; 434 + delete[] sourceBuffer; 435 + 436 + return 0; 437 + } 438 + 439 + std::string GetCurrentPath() { 440 + char buffer[MAX_PATH]; 441 + GetModuleFileNameA(NULL, buffer, MAX_PATH); 442 + std::string::size_type pos = std::string(buffer).find_last_of("\\/"); 443 + return std::string(buffer).substr(0, pos); 444 + } 445 + 446 + std::string GenerateRandomFolderName() { 447 + std::random_device rd; 448 + std::mt19937 gen(rd()); 449 + std::uniform_int_distribution<int> dist(1, 1000000); 450 + 451 + // 生成随机字符串作为文件夹名 452 + const char charset[] = "ghijklmnopq_rstuvwxyz0123456789abcdef"; 453 + const size_t charsetSize = sizeof(charset) - 1; 454 + const size_t folderNameLength = 10; // 文件夹名长度 455 + std::string folderName; 456 + for (size_t i = 0; i < folderNameLength; ++i) { 457 + folderName += charset[dist(gen) % charsetSize]; 458 + } 459 + return folderName; 460 + } 461 + 462 + string CreateRandomFolder(const std::string& basePath) { 463 + std::string randomFolderName = GenerateRandomFolderName(); 464 + std::string folderPath = basePath + "\\" + randomFolderName; 465 + 466 + if (CreateDirectoryA(folderPath.c_str(), NULL) || GetLastError() == ERROR_ALREADY_EXISTS) { 467 + return folderPath; 468 + } 469 + 470 + return 0; 471 + } 472 + 388 473 std::wstring ConvertToWideString(const char* input) { 389 474 int length = strlen(input) + 1; 390 475 int requiredLength = MultiByteToWideChar(CP_ACP, 0, input, length, NULL, 0); skipped 3 lines 394 479 delete[] buffer; 395 480 return result; 396 481 } 482 + 483 + string CopyFileToFolder(const std::string& sourceFilePath, const std::string& targetFolderPath, bool isNeedHook, bool isPreDll, int bit) { 484 + std::string targetFilePath = targetFolderPath + "\\" + sourceFilePath.substr(sourceFilePath.find_last_of("\\/") + 1); 485 + 486 + if (isNeedHook) { 487 + std::string hookFilePath = GetCurrentPath() + "\\TestLoad_x86.dll"; 488 + if (bit == 64) 489 + hookFilePath = GetCurrentPath() + "\\TestLoad_x64.dll"; 490 + 491 + if (isPreDll) { 492 + CopyFileA(hookFilePath.c_str(), targetFilePath.c_str(), FALSE); 493 + fixExportTable(targetFilePath, sourceFilePath); 494 + } 495 + else { 496 + CopyFileA(hookFilePath.c_str(), targetFilePath.c_str(), FALSE); 497 + } 498 + } 499 + else { 500 + CopyFileA(sourceFilePath.c_str(), targetFilePath.c_str(), FALSE); 501 + } 502 + 503 + return targetFilePath; 504 + } 505 + 506 + bool DeleteDirectory(const string& path) { 507 + WIN32_FIND_DATAA findData; 508 + HANDLE hFind = FindFirstFileA((path + "\\*").c_str(), &findData); 509 + 510 + if (hFind == INVALID_HANDLE_VALUE) { 511 + return false; 512 + } 513 + 514 + do { 515 + if (strcmp(findData.cFileName, ".") != 0 && strcmp(findData.cFileName, "..") != 0) { 516 + string filePath = path + "\\" + findData.cFileName; 517 + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 518 + // 递归删除子目录 519 + if (!DeleteDirectory(filePath)) { 520 + FindClose(hFind); 521 + return false; 522 + } 523 + } 524 + else { 525 + // 删除文件 526 + DWORD fileAttributes = GetFileAttributesA(filePath.c_str()); 527 + !SetFileAttributesA(filePath.c_str(), fileAttributes & ~FILE_ATTRIBUTE_READONLY); 528 + 529 + if (!DeleteFileA(filePath.c_str())) { 530 + FindClose(hFind); 531 + return false; 532 + } 533 + } 534 + } 535 + } while (FindNextFileA(hFind, &findData) != 0); 536 + 537 + FindClose(hFind); 538 + 539 + // 删除空目录 540 + if (!RemoveDirectoryA(path.c_str())) { 541 + return false; 542 + } 543 + 544 + return true; 545 + } 546 + 547 + int TestCreateProcess(string runFilePath) { 548 + // 定义进程信息结构体 549 + STARTUPINFOA si = { sizeof(si) }; 550 + PROCESS_INFORMATION pi; 551 + 552 + // 创建进程 553 + if (!CreateProcessA( 554 + nullptr, // 指向可执行文件名的指针(在这里,nullptr表示使用当前可执行文件) 555 + (char*)runFilePath.c_str(), // 可执行文件的路径 556 + nullptr, // 安全属性 557 + nullptr, // 安全属性 558 + FALSE, // 指定是否继承句柄 559 + CREATE_NO_WINDOW, // 指定窗口显示方式(这里指定为无窗口) 560 + nullptr, // 指定新进程的环境块 561 + nullptr, // 指定新进程的当前目录 562 + &si, // STARTUPINFO 结构体 563 + &pi)) { // 接收新进程信息的 PROCESS_INFORMATION 结构体 564 + std::cerr << "Failed to create process. Error code: " << GetLastError() << std::endl; 565 + return 1; 566 + } 567 + 568 + // 等待进程结束 569 + WaitForSingleObject(pi.hProcess, 2 * 1000); 570 + 571 + TerminateProcess(pi.hProcess, 0); 572 + 573 + // 获取进程的退出码 574 + DWORD exitCode; 575 + GetExitCodeProcess(pi.hProcess, &exitCode); 576 + 577 + // 输出退出码 578 + std::cout << runFilePath << " Process exited with code: " << exitCode << std::endl; 579 + 580 + // 关闭进程和线程句柄 581 + CloseHandle(pi.hProcess); 582 + CloseHandle(pi.hThread); 583 + 584 + return 0; 585 + } 586 + 587 + void RunPE() { 588 + std::string currentPath = GetCurrentPath(); 589 + 590 + for (const auto& result : results) { 591 + string folderPath = CreateRandomFolder(currentPath); 592 + 593 + string runFilePath = CopyFileToFolder(result->filePath, folderPath, false, false, result->bit); 594 + 595 + bool flag; 596 + if (result->preLoadDlls.size() > 0) { 597 + flag = result->preLoadDlls.size() <= c.dllCount ? true : false; 598 + 599 + for (const auto& dll : result->preLoadDlls) { 600 + CopyFileToFolder(result->fileDir + dll, folderPath, flag, true, result->bit); 601 + } 602 + } 603 + 604 + if (result->postLoadDlls.size() > 0) { 605 + flag = result->postLoadDlls.size() <= c.dllCount ? true : false; 606 + 607 + for (const auto& dll : result->postLoadDlls) { 608 + CopyFileToFolder(result->fileDir + dll, folderPath, flag, false, result->bit); 609 + } 610 + } 611 + 612 + TestCreateProcess(runFilePath); 613 + 614 + DeleteDirectory(folderPath.c_str()); 615 + } 616 + }