第13節 第二種shellcode編寫實戰(2)

在第二種shellcode編寫實戰(1)的基礎上,新增加一個CAPI類,將所有用到的函數都在這個類中做動態調用的處理,這樣使得整個shellcode功能結構更加清晰。

1. 新建類CAPI(即api.h和api.cpp兩個文件):

api.h:

#pragma once#include <windows.h>
#include <Winternl.h>class CAPI
{
private:HMODULE GetKernel32BaseAddress();FARPROC _GetPorcAddress();public:void InitFunctions();public:typedef HANDLE(WINAPI* FN_CreateFileA)(_In_ LPCSTR lpFileName,_In_ DWORD dwDesiredAccess,_In_ DWORD dwShareMode,_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,_In_ DWORD dwCreationDisposition,_In_ DWORD dwFlagsAndAttributes,_In_opt_ HANDLE hTemplateFile);typedef int (WINAPI* FN_MessageBoxA)(__in_opt HWND hWnd,__in_opt LPCSTR lpText,__in_opt LPCSTR lpCaption,__in UINT uType);typedef HMODULE(WINAPI* FN_LoadLibraryA)(__in LPCSTR lpLibFileName);public:FN_CreateFileA CreateFileA;FN_MessageBoxA MessageBoxA;FN_LoadLibraryA LoadLibraryA;
};

api.cpp:

#include "api.h"// 獲取kernel32基址
HMODULE CAPI::GetKernel32BaseAddress()
{HMODULE hKernel32 = NULL;// 用戶保存模塊名WCHAR wszModuleName[MAX_PATH];#ifdef _WIN64    // 64位PEB偏移為0x60PPEB lpPeb = (PPEB)__readgsqword(0x60);
#else            // 32位PEB偏移為0x30PPEB lpPeb = (PPEB)__readfsdword(0x30);
#endifPLIST_ENTRY pListHead = &lpPeb->Ldr->InMemoryOrderModuleList;PLIST_ENTRY pListData = pListHead->Flink;// 遍歷所有模塊while (pListData != pListHead){PLDR_DATA_TABLE_ENTRY pLDRData = CONTAINING_RECORD(pListData, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);DWORD dwLen = pLDRData->FullDllName.Length / 2;if (dwLen > 12)    // 12 是"kernel32.dll"的長度,獲取到的完整路徑肯定要比模塊名長{// 從獲取到的模塊完整路徑中提取模塊名for (size_t i = 0; i < 12; i++){wszModuleName[11 - i] = pLDRData->FullDllName.Buffer[dwLen - 1 - i];}// 最終要獲取的目標模塊名("kernel32.dll"),逐個字節比較,包含大小寫。if ((wszModuleName[0] == 'k' || wszModuleName[0] == 'K') &&(wszModuleName[1] == 'e' || wszModuleName[1] == 'E') &&(wszModuleName[2] == 'r' || wszModuleName[2] == 'R') &&(wszModuleName[3] == 'n' || wszModuleName[3] == 'N') &&(wszModuleName[4] == 'e' || wszModuleName[4] == 'E') &&(wszModuleName[5] == 'l' || wszModuleName[5] == 'L') &&(wszModuleName[6] == '3') &&(wszModuleName[7] == '2') &&(wszModuleName[8] == '.') &&(wszModuleName[9] == 'd' || wszModuleName[9] == 'D') &&(wszModuleName[10] == 'l' || wszModuleName[10] == 'L') &&(wszModuleName[11] == 'l' || wszModuleName[11] == 'L')){hKernel32 = (HMODULE)pLDRData->DllBase;break;}}pListData = pListData->Flink;}return hKernel32;
}// 獲取GetPorcAddress函數地址
FARPROC CAPI::_GetPorcAddress()
{// 保存最終結果FARPROC pGetPorcAddress = NULL;// kernel32基址HMODULE hKernel32 = GetKernel32BaseAddress();if (!hKernel32){return NULL;}PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hKernel32;PIMAGE_NT_HEADERS lpNTHeader = (PIMAGE_NT_HEADERS)((unsigned char*)hKernel32 + lpDosHeader->e_lfanew);// 模塊有效性驗證if (!lpNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size){return NULL;}if (!lpNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress){return NULL;}// 通過導出表中的導出函數名,定位"GetProcAddress"的位置PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((unsigned char*)hKernel32 + lpNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);PDWORD lpdwFunName = (PDWORD)((unsigned char*)hKernel32 + lpExports->AddressOfNames);PWORD lpdwOrd = (PWORD)((unsigned char*)hKernel32 + lpExports->AddressOfNameOrdinals);PDWORD lpdwFunAddr = (PDWORD)((unsigned char*)hKernel32 + lpExports->AddressOfFunctions);for (DWORD dwLoop = 0; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++){char* pFunName = (char*)(lpdwFunName[dwLoop] + (unsigned char*)hKernel32);// 比較函數名if (pFunName[0] == 'G' &&pFunName[1] == 'e' &&pFunName[2] == 't' &&pFunName[3] == 'P' &&pFunName[4] == 'r' &&pFunName[5] == 'o' &&pFunName[6] == 'c' &&pFunName[7] == 'A' &&pFunName[8] == 'd' &&pFunName[9] == 'd' &&pFunName[10] == 'r' &&pFunName[11] == 'e' &&pFunName[12] == 's' &&pFunName[13] == 's'){pGetPorcAddress = (FARPROC)(lpdwFunAddr[lpdwOrd[dwLoop]] + (unsigned char*)hKernel32);break;}}return pGetPorcAddress;
}// 初始化所有用到的函數
void CAPI::InitFunctions()
{// 獲取GetPorcAddress函數地址typedef FARPROC(WINAPI* FN_GetProcAddress)(__in HMODULE hModule, __in LPCSTR lpProcName);FN_GetProcAddress fn_GetProcAddress = (FN_GetProcAddress)_GetPorcAddress();if (fn_GetProcAddress){// 獲取LoadLibraryA函數地址char szLoadLibraryA[] = { 'L','o','a','d','L','i','b','r','a','r','y','A',0 };LoadLibraryA = (FN_LoadLibraryA)fn_GetProcAddress(GetKernel32BaseAddress(), szLoadLibraryA);if (LoadLibraryA){// 獲取MessageBoxA函數地址char szUser32[] = { 'U','s','e','r','3','2','.','d','l','l',0 };char szMessageBoxA[] = { 'M','e','s','s','a','g','e','B','o','x','A',0 };MessageBoxA = (FN_MessageBoxA)fn_GetProcAddress(LoadLibraryA(szUser32), szMessageBoxA);// 獲取CreateFileA函數地址char szCreateFileA[] = { 'C','r','e','a','t','e','F','i','l','e','A',0 };CreateFileA = (FN_CreateFileA)fn_GetProcAddress(GetKernel32BaseAddress(), szCreateFileA);}}
}

2. 在CAPI中,使用InitFunctions函數來初始化所有shellcode中用到的函數,在shellcode執行功能處,進行如下調用即可(a.start.cpp):

#include "a.start.h"
#include "shellcode.h"
#include "api.h"void ShellCodeStart()
{CAPI api;// 初始化所有用到的函數api.InitFunctions();CDoShellcode shellcode;// 創建文件shellcode.DoCreateFile(&api);// 彈框提示shellcode.DoMessageBox(&api);// 其他功能...
}

3. 在類CDoShellcode中,將所有函數功能執行的參數都傳遞一個CAPI的指針變量,那么所有功能都可以使用CAPI中的函數。比如CDoShellcode中的DoCreateFile方法:

// 功能:創建文件 D:\1.txt
int CDoShellcode::DoCreateFile(CAPI* api)
{// 執行動態CreateFileA,創建文件char szFilePath[] = { 'D',':','\\','1','.','t','x','t',0 };api->CreateFileA(szFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);return 0;
}

如此一來,對類CDoShellcode而言,我們只關注功能的實現,不必再顧及函數動態調用的問題。所有用到的動態函數的實現都可以共享CAPI中的實現。

項目結構:

兩個類:

  • CDoShellcode(shellcode.h和shellcode.cpp):shellcode執行的各類功能;
  • CAPI(api.h和api.cpp):所有shellcode使用到的動態函數。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10832.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10832.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10832.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

#DELPHI BASS庫Windows平臺下,實時更換輸出設備

DELPHI BASS庫Windows平臺下&#xff0c;實時更換輸出設備 #DELPHI BASS庫Windows平臺下&#xff0c;實時更換輸出設備 取自網絡&#xff0c;分享&#xff0c;項目嵌入無損音樂播放后&#xff0c;畫蛇添足的功能分享&#xff01; 直接貼核心代碼&#xff0c;看不明白去看說…

flutter自定義日期選擇器按日、按月、自定義開始、結束時間

導入包flutter_datetime_picker: 1.5.0 封裝 import package:atui/jade/utils/JadeColors.dart; import package:flutter/cupertino.dart; import package:flutter/material.dart; import package:flutter_datetime_picker/flutter_datetime_picker.dart; import package:flut…

景源暢信電商:經營抖店需要電腦嗎?

經營抖店是否需要電腦?這個問題看似簡單&#xff0c;實則關乎著商家的運營效率和成本投入。在當前數字化、網絡化的商業環境中&#xff0c;電腦已經成為了不可或缺的工具。那么&#xff0c;經營抖店究竟是否需要電腦呢?答案是肯定的。 一、高效處理訂單 電腦能夠高效地處理大…

Mysql FLOAT和DOUBLE類型區別

存儲方式&#xff1a; FLOAT和DOUBLE是浮點數類型&#xff0c;它們以二進制格式存儲數值&#xff0c;可以存儲近似值。這意味著某些特定的小數值可能無法精確表示&#xff0c;可能會有微小的計算誤差。DECIMAL是定點數類型&#xff0c;以字符串形式存儲數值&#xff0c;可以存儲…

從零學算法2105

2105. 給植物澆水 II Alice 和 Bob 打算給花園里的 n 株植物澆水。植物排成一行&#xff0c;從左到右進行標記&#xff0c;編號從 0 到 n - 1 。其中&#xff0c;第 i 株植物的位置是 x i 。 每一株植物都需要澆特定量的水。Alice 和 Bob 每人有一個水罐&#xff0c;最初是滿的…

如何在湖師大官網找到考研真題

今天學弟問我怎么找真題&#xff0c;我必須告訴他怎么找湖師大的真題&#xff0c;身為考研學子&#xff0c;這是必須要知道滴&#xff0c;尤其是自命題&#xff0c;是吧&#xff0c;話不多說&#xff0c;言歸正傳&#xff0c;我們開始吧&#xff01; 1 打開湖師大官網 什么&a…

樹莓派nmap掃描

debian系統安裝nmap&#xff1a; sudo apt install nmap安裝nmap完成后&#xff0c;輸入 ip route 來查看當前Wi-Fi路由器的ip地址。 第一行的default via后顯示的便是網關地址&#xff0c;也就是路由器地址。 獲取到路由器ip地址后&#xff0c;在終端中輸入&#xff1a; …

一站式HMI軟件開發套件eStation,讓開發更簡單高效

4月份舉辦的北京國際車展上全球首發車117輛&#xff0c;新能源車型278個&#xff0c;越來越多的車廠通過差異化和改善UI/UE體驗&#xff0c;來獲取更多用戶的青睞。為快速響應差異化競爭需求&#xff0c;智能座艙HMI市場遇到以下挑戰&#xff1a; 如何兼容不同項目開發人員編程…

C# 使用SendMessage進行進程通信,可發送字符串,結構體

發送時只能以結構體形式發送&#xff0c;類的話會提示“指定結構必須能直接復制到本機結構中&#xff0c;或是具有布局信息 ”的錯誤提示 以下兩種結構體示例都可以被發送 public struct A{public A(int a){name "heow";array new double[3] { 1, 2, 5.6 };}strin…

批量為本地視頻生成字幕文件,并可將字幕文件翻譯成其它語言

VideoSubtitleGenerator 批量為本地視頻生成字幕文件&#xff0c;并可將字幕文件翻譯成其它語言 本項目基于 macOS, node 環境運行&#xff0c;暫未兼容 windows 環境 &#x1f310;Github地址 https://github.com/buxuku/VideoSubtitleGenerator 初衷 自己有一大批外文視頻&…

力扣例題(用棧實現隊列)

目錄 鏈接. - 力扣&#xff08;LeetCode&#xff09; 描述 思路 push pop peek empty 代碼 鏈接. - 力扣&#xff08;LeetCode&#xff09; 描述 思路 push 例如我們將10個元素放入棧中&#xff0c;假設最左邊為棧頂&#xff0c;最右側為棧底 則為10,9,8,7,6,5,4,3,…

嵌入式 - GPIO編程簡介

An Introduction to GPIO Programming By Jeff Tranter Wednesday, June 12, 2019 編者按&#xff1a;本 2019 年博客系列是 ICS 最受歡迎的系列之一&#xff0c;現已更新&#xff08;2022 年 12 月&#xff09;&#xff0c;以確保內容仍然準確、相關和有用。 本博客是 Integr…

實體類和Entity Class之間有什么聯系

實體類&#xff08;Entity Class&#xff09;和Entity Class在本質上是相同的&#xff0c;它們都是面向對象編程&#xff08;OOP&#xff09;中用于表示具有業務邏輯意義的實體的類。 具體來說&#xff0c;實體類通常被設計用于代表真實世界中的對象或概念&#xff0c;這些對象…

PWRWER

編譯燒錄完代碼之后&#xff0c;按下復位鍵屏幕會進行刷新&#xff0c;數據不會丟失 如果按下按鍵&#xff0c;進行頁擦除&#xff0c;之后再按下復位鍵&#xff0c;發現屏幕不會再進行刷新&#xff0c;原因是程序已經被擦除&#xff0c;損毀&#xff0c;無法運行&#xff0c;此…

2024OD機試卷-查找接口成功率最優時間段 (java\python\c++)

題目:查找接口成功率最優時間段 題目描述 服務之間交換的接口成功率作為 服務調用 關鍵質量特性,某個時間段內的接口失敗率使用一個數組表示, 數組中每個元素都是單位時間內失敗率數值,數組中的數值為0~100的整數, 給定一個數值(minAverageLost)表示某個時間段內平均失敗…

圖片轉word如何轉換?

要將圖片轉換為Word文檔&#xff0c;你可以使用以下方法之一&#xff1a; 以上這些方法都可以幫助你將圖片中的文本轉換為可編輯的Word文檔&#xff0c;你可以根據自己的喜好和需求選擇其中一種方法來操作。 使用OCR軟件或在線工具&#xff1a;有許多OCR&#xff08;Optical Ch…

【數據庫】為何選擇B+樹作為索引?與紅黑樹、B樹的對比

摘要&#xff1a; 數據庫索引是數據庫系統中至關重要的組成部分&#xff0c;影響著數據檢索的效率和性能。本文將探討為何數據庫選擇B樹作為索引的原因&#xff0c;并分別分析紅黑樹和B樹在此場景中的劣勢。 介紹&#xff1a; 數據庫索引是數據庫系統中的重要組成部分&#xf…

實戰LangChain(六):深入LangGraph的高級功能與最佳實踐

實戰LangChain(六):深入LangGraph的高級功能與最佳實踐 實戰LangChain(一):構建您的第一個聊天機器人_langchai 機器人 實戰LangChain(二):探索RAG——為聊天機器人注入知識-CSDN博客 實戰LangChain(三):深化交互——利用Neo4j提升聊天機器人的對話能力 實戰La…

電子資源|基于SSM+vue的電子資源管理系統(源碼+數據庫+文檔)?

電子資源管理系統 目錄 基于SSMvue的電子資源管理系統 一、前言 二、系統設計 三、系統功能設計 1系統功能模塊 2管理員功能模塊 5.2.1管理員功能模塊 5.2.2用戶功能模塊 四、數據庫設計 五、核心代碼 六、論文參考 七、最新計算機畢設選題推薦 八、源碼獲取&am…

【Qt 學習筆記】Qt常用控件 | 多元素控件 | Tree Widget的說明及介紹

博客主頁&#xff1a;Duck Bro 博客主頁系列專欄&#xff1a;Qt 專欄關注博主&#xff0c;后期持續更新系列文章如果有錯誤感謝請大家批評指出&#xff0c;及時修改感謝大家點贊&#x1f44d;收藏?評論? Qt常用控件 | 多元素控件 | Tree Widget的說明及介紹 文章編號&#x…