Atack of Titan

This is Day 9 of the monicle Advent Calendar! https://adventar.org/calendars/8977 tl;dr Active Directory exploitation involves unauthorized actions by attackers to compromise, manipulate, or gain unauthorized access to an organization’s Active Directory infrastructure. This can include stealing credentials, using password hashes, forging tickets, escalating privileges, moving laterally within the network, and establishing persistent access. Organizations should implement security measures to detect and mitigate these threats. What is Active Directory Active Directory (AD) is a directory service developed by Microsoft for Windows domain networks....

<span title='2023-12-09 00:00:00 +0000 UTC'>December 9, 2023</span>&nbsp;·&nbsp;19 min&nbsp;·&nbsp;3960 words&nbsp;·&nbsp;FAMASoon

DLL proxying with Rust

DLL proxying with Rust what is dll proxying? DLL proxying, also known as DLL redirection or DLL hijacking, is a technique used by attackers or developers to manipulate the way Windows loads dynamic link libraries (DLLs). DLLs are files that contain code and data that multiple programs can use simultaneously. They provide a way to modularize code and promote code reuse. DLL proxying involves placing a malicious or modified DLL in a location that is searched by a target application before the legitimate DLL is located....

<span title='2023-11-23 00:00:00 +0000 UTC'>November 23, 2023</span>&nbsp;·&nbsp;3 min&nbsp;·&nbsp;521 words&nbsp;·&nbsp;FAMASoon

Anti-debug introduction

Anti-debug アンチデバッグのやり方はたくさんあるが、その中でもよく使われるものを紹介する。 網羅的に把握したい場合は下記リンクを参照すると良い。 https://unprotect.it/category/anti-debugging/ 古典的なアンチデバッグ bool FindDebugger() { bool bDetect = false; HWND hDebugger = ::FindWindow(NULL, "OllyDBG"); if (hDebugger) { bDetect = true; AfxMessageBox("Can not use debugger"); } return bDetect; } デバッガーのウィンドウキャプションを見つけてプログラムを終了させる。 IsDebuggerPresent MSDNに記載されていてkernel32.dllから提供されている。 if (IsDebuggerPresent()) { exit(1); } アセンブリになると下記のようになる mov eax, dword ptf fs:[18] mov eax, dword ptr ds:[eax+30] movzx eax, byte ptr ds:[eax+2] retn fs:[18] はTEBを指す。(Thread Environment Block) TEBをEAXに入れたがそこから30番地離れたアドレスを再びEAXに入力するコードだ。 TEBから0x30離れたところにはPEB(Process Environment Block) がある。 EAXにはPEBが入っていて、そこから+2移動したアドレスから1バイト持ってきていると解釈できる。 PEBの構造体は下記の通り。 typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID Reserved4[3]; PVOID AtlThunkSListPtr; PVOID Reserved5; ULONG Reserved6; PVOID Reserved7; ULONG Reserved8; ULONG AtlThunkSListPtr32; PVOID Reserved9[45]; BYTE Reserved10[96]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved11[128]; PVOID Reserved12[1]; ULONG SessionId; } PEB, *PPEB; BeingDebugged という名前の箇所の値を入れている。...

<span title='2023-10-12 00:00:00 +0000 UTC'>October 12, 2023</span>&nbsp;·&nbsp;5 min&nbsp;·&nbsp;854 words&nbsp;·&nbsp;FAMASoon

AMSI bypass

スキャン要求を失敗させるために、すでにメモリにロードされているAMSI ライブラリ自体のコードを改ざんする. メモリにすでにロードされている AmsiScanBuffer というライブラリを探し出し、そのアドレスの命令を上書きしてエラーメッセージを表示させます。この攻撃では、マルウェアがメモリ内のライブラリ「AmsiScanBuffer」を探し出し、そのアドレスの命令を、エラーメッセージにリダイレクトする新しい命令で上書きします。 [package] name = "amsibypass" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] name = "amsi_bypass" path = "src/main.rs" [dependencies] winapi = {version = "0.3.9", features=["memoryapi", "libloaderapi", "processthreadsapi"]} win32-error = "0.9.0" use std::{ffi::CString, ptr}; use winapi::{ um::{ memoryapi::{ VirtualProtect, WriteProcessMemory }, libloaderapi::{ LoadLibraryA, GetProcAddress }, processthreadsapi::GetCurrentProcess, winnt::PAGE_READWRITE }, shared::{ minwindef::{ DWORD, FALSE }, ntdef::NULL } }; fn main() { println!...

<span title='2023-10-11 00:00:00 +0000 UTC'>October 11, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;167 words&nbsp;·&nbsp;FAMASoon

Offensive Rustのレビュー

Offensive Rust かんたんなまとめ: Rustでレッドチームシミュレータを書きたい人におすすめ。 リンク https://redteamsorcery.teachable.com/courses/enrolled/1973492 https://www.udemy.com/course/offensive-rust/ アフィリエイトはないです。 概要 本教材ではオフェンシブなコード、レッドチーム向けのコードをRustで書いていく。 なお、対象環境はWindows。 WSLとかではなくWindowsに直接Rustをインストールする。 内容 内容はかなり多岐にわたる。 最初の方ではRustのセットアップを実施し、基礎的なRustの書き方を教えてくれる。 中盤からはオフェンシブなコードを書いていく。 例えばLDAPを用いたActive Directoryの列挙であったり、シェルコードを書いたり、DLLインジェクションを行ったりと、基本的なRustの書き方を抑えつつレッドチーム向けのコードを書いていく。 また、Reflective PE Loaderを書いたり、Process Hollowingをやったり、ハッシュ化した関数呼び出しをしたりとレッドチームシミュレータで実行しそうな内容をRustでどのように書くか教えてくれる。 以降もAMSIのバイパスの仕方やProcess Doppelgangingの仕方をRustで解説してくれる。 総じてレッドチームシミュレータをRustで書いてみたいと方にはおすすめの内容。 各パートは体感ではそこまで長くなく、サッと書いてサッと試すということをやっていく。 まとめ レッドチーム向けのシミュレータを書きたいとなったとき、候補としてはC/C++が挙がるがRustで書きたい人は、この教材を買って見てみると良いだろう。

<span title='2023-10-11 00:00:00 +0000 UTC'>October 11, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;28 words&nbsp;·&nbsp;FAMASoon

PEについてメモ

What is PE PEファイルとはPortable Executable File Formatの略。 ポータブルな実行ファイルである。 ビルド たとえばtest.cppといったファイルを作成してビルドすると、まず関連するヘッダーとソースをコンパイルし1つの機械語コードを作成する。 この段階でReleaseディレクトリにobjファイルが生成される。 次にリンク作業が行われる。 リンカはOSでこのファイルを実行できるように動的ライブラリや様々なリソースデータ、インポート・エクスポートテーブルを処理するための情報をファイルに書き出す。 この際にWindowsは決まったルールに沿って情報を用意しExeファイルを作成する際に、ヘッダーに情報を書き込む。 これがPEフォーマットを作成する処理である。 PEヘッダーの中には実行ファイルを実行するために様々な情報が記録されている。 PEファイルの構造 IMAGE_DOS_HEADER IMAGE_NT_HEADER IMAGE_FILE_HEADER IMAGE_OPTIONAL_HEADER IMAGE_SECTION_HEADER IMAGE_IMPORT_DESCRIPTOR IMAGE_EXPORT_DIRECTORY IMAGE_IMPORT_BY_NAME IMAGE_THUNK_DATA32 主要な構造体は上記の通り。 IMAGE_DOS_HEADER typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number WORD e_cblp; // Bytes on last page of file WORD e_cp; // Pages in file WORD e_crlc; // Relocations WORD e_cparhdr; // Size of header in paragraphs WORD e_minalloc; // Minimum extra paragraphs needed WORD e_maxalloc; // Maximum extra paragraphs needed WORD e_ss; // Initial (relative) SS value WORD e_sp; // Initial SP value WORD e_csum; // Checksum WORD e_ip; // Initial IP value WORD e_cs; // Initial (relative) CS value WORD e_lfarlc; // File address of relocation table WORD e_ovno; // Overlay number WORD e_res[4]; // Reserved words WORD e_oemid; // OEM identifier (for e_oeminfo) WORD e_oeminfo; // OEM information; e_oemid specific WORD e_res2[10]; // Reserved words LONG e_lfanew; // File address of new exe header } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; e_magic , e_lfanew について注目するとよい。...

<span title='2023-07-21 00:00:00 +0000 UTC'>July 21, 2023</span>&nbsp;·&nbsp;3 min&nbsp;·&nbsp;590 words&nbsp;·&nbsp;FAMASoon

LibFuzzerを使った

LibFuzzerを使った https://x64.moe/posts/whatslibfuzzer/ こんな感じにファジングできるLibFuzzerを使ってみた。 結論としてはどれもうまくいかなかった(クラッシュしない・クラッシュしても配布されるビルドのものだとクラッシュしない等など) ターゲット Jansson https://github.com/akheron/jansson なんかのパーサがやりやすいかなと思ってJSONパーサのJanssonを選んだ。 #include <stddef.h> #include <stdint.h> #include "jansson.h" int parseJson(const char *buffer, size_t buflen) { json_error_t error; json_t *root; json_t *obj; const char *str; double dValue; int iValue; root = json_loadb(buffer, buflen, 0, &error); if (root == NULL) { return 0; } obj = json_object_get(root, "dateTime"); if (json_is_string(obj)) { str = json_string_value(obj); } obj = json_object_get(root, "eventType"); if (json_is_string(obj)) { str = json_string_value(obj); } obj = json_object_get(root, "DependOnSequentialEvent"); if (json_is_object(obj)) { json_t *obj2; obj2 = json_object_get(obj, "valPercent"); if (json_is_real(obj2)) { dValue = json_real_value(obj2); } else if (json_is_integer(obj2)) { iValue = json_integer_value(obj2); } obj2 = json_object_get(obj, "alive"); if (json_is_string(obj2)) { str = json_string_value(obj2); } obj2 = json_object_get(obj, "isScript"); } return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 0) { return -1; } parseJson((const char *)data, size); return 0; } ビルド内容は下記のような感じ クラッシュしなかった。...

<span title='2023-07-04 00:00:00 +0000 UTC'>July 4, 2023</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;306 words&nbsp;·&nbsp;FAMASoon

LibFuzzer's Example

What is LibuFuzzer? Libfuzzer is a library part of LLVM that can be used to fuzz test programs. Example Build the fuzzing target. #include <stdint.h> #include <stddef.h> bool FuzzMe(const uint8_t *Data, size_t DataSize) { return DataSize >= 3 && Data[0] == 'F' && Data[1] == 'U' && Data[2] == 'Z' && Data[3] == 'Z'; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { FuzzMe(Data, Size); return 0; } First, write LLVMFuzzerTestOneInput function....

<span title='2023-06-29 00:00:00 +0000 UTC'>June 29, 2023</span>&nbsp;·&nbsp;4 min&nbsp;·&nbsp;805 words&nbsp;·&nbsp;FAMASoon

[Note] LibAFLとはなにか

LibAFL とは https://aflplus.plus/libafl-book/libafl.html ファジングのためのライブラリ。 AFL, libFuzzer, honggfuzz といったファザーは存在するが拡張性がない。 個々のソフトウェアに対してカスタマイズ可能なファザーを作るために開発された。 特徴 マルチプラットフォーム対応 OS依存のランタイムを必要としていない なので組み込みデバイスやハイパーバイザ、WASMなどにつかえる(らしい) AFLPlusPlusで培った経験が活かされている スケールしやすいらしい 早い ソフトウェアに合わせてカスタムできる 入門 crate として使える。 注意点としてClangに依存しているので予めインストールする必要がある。 各種プロジェクトのルートディレクトリから cargo build --release を実行することでビルドできる。 下記のように Cargo.toml に書けば良い(私は cargo add で入れた) [dependencies] libafl = { version = "*" } 色々とカスタムできるがクレートとしては libafl を使えば良さそう。 他のクレートの説明はこちら。 https://aflplus.plus/libafl-book/getting_started/crates.html コンセプト Observer テスト対象のぷろぐらむの実行を監視し、その情報をファザーに提供するものです。 これは Observer トレイトに書かれている。 各ファジングのデータを保持したりファジングケースの前後でフックしたりできる。 Executor テスト対処の実行に関する操作を定義するもの。 ファザー=が実行で使用したい入力についてプログラムに通知し、特定のメモリの場所に書き込んだり、それをパラメータとしてハーネスに渡す責任がある。 Executor トレイとで提供されている。 InprocessExecutor はプロセス内のクラッシュを検出する。 ForkserverExecutor 子プロセスをファズするときに使う。 InprocessExecotr はファザープロセス内のハーネスを実行する。 ハーネスをできるだけ早く実行したいときはこれを採用する。 注意するべき点はハーネスにヒープ周りのバグがある可能性がある場合、クラッシュしたヒープがファザーに影響を与えないように別のアロケータを使用する必要があります。 例えばMiMallocを使用するなど。 あるいはアドレスサニタイザーを使用してハーネスをコンパイルしヒープ周りのバグを補足できるようにする。 ForkserverExecutor は共有メモリを使用してハーネスを実行する。 InprocessForkExecutor はハーネスを実行する前に分岐する。 ハーネスが不安定になったりクラッシュするような場合、子プロセスでハーネスを実行する必要がある。 そのような時に使用する。 ただしハーネスを実行し、カバレッジをマップに書くのは子プロセス。 親プロセスと子プロセスの間でマップを共有するために共有メモリを使用する。...

<span title='2023-06-10 00:00:00 +0000 UTC'>June 10, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;104 words&nbsp;·&nbsp;FAMASoon

Dll Injection with Rust

winapi winapi provides raw FFI bindings to all of Windows API. So, I will use this crate. code When run command cargo run, it can be inject dll to process use winapi::ctypes::*; use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress}; use winapi::um::memoryapi::{VirtualAllocEx, WriteProcessMemory}; use winapi::um::processthreadsapi::{CreateRemoteThread, OpenProcess}; pub fn DllInject(proc_handle: *mut c_void, dll_path: &str) { unsafe { let remote_base = VirtualAllocEx( proc_handle, std::ptr::null_mut(), dll_path.len(), 0x1000, 0x40, ); WriteProcessMemory( proc_handle, remote_base, dll_path.as_bytes().as_ptr() as *const c_void, dll_path.len(), std::ptr::null_mut(), ); let dll_handle = GetModuleHandleA("kernel32....

<span title='2023-06-06 00:00:00 +0000 UTC'>June 6, 2023</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;129 words&nbsp;·&nbsp;FAMASoon