Security Research | Reverse Engineering | Low-Level Exploration
PixelBlog_
PixelBlog_
PixelBlog_
Security Research | Reverse Engineering | Low-Level Exploration
PixelBlog Reborn Welcome to the new PixelBlog. After running on Flask for a while, I decided to rebuild the entire blog as a static site using Hugo. Why the change? Performance: Static files served directly by Nginx — no Python runtime overhead Security: No application server = no application-layer attack surface Simplicity: No Docker, no database, no WSGI server — just Markdown + hugo build Version Control: All content lives in Git, deployed with a single command What’s new? Dark theme by default, with a retro pixel aesthetic JetBrains Mono for code, Press Start 2P for headings Chroma syntax highlighting with Dracula theme Full-text search powered by Fuse.js RSS feed support What stays the same? The focus remains on security research, reverse engineering, and low-level exploration. Expect more write-ups on Windows internals, Rust for security tooling, and CTF solutions. ...
Introduction Static analysis is the art of understanding a program without running it. It’s the first step in any reverse engineering workflow and often reveals enough to understand what a binary does. Essential Tools Disassemblers Tool Platform Notes Ghidra Cross-platform Free, decompiler included IDA Pro Cross-platform Industry standard, expensive Binary Ninja Cross-platform Modern API, mid-range price radare2 Cross-platform CLI-based, scriptable File Analysis 1 2 3 4 5 6 7 8 9 10 11 12 # Basic file identification file target_binary # Check security mitigations checksec --file=target_binary # List imported symbols nm -D target_binary objdump -T target_binary # List strings strings -n 8 target_binary | less Reading Assembly The key skill is reading disassembly output. Here’s a simple example: ...
Overview DLL injection is a classic technique where you force a running process to load a DLL of your choosing. While often associated with malware, it’s also used legitimately by debuggers, profilers, and mod frameworks. We’ll implement the CreateRemoteThread injection method in Rust. The Win32 API Chain The injection follows this sequence: OpenProcess — get a handle to the target process VirtualAllocEx — allocate memory in the target WriteProcessMemory — write the DLL path string CreateRemoteThread — spawn a thread that calls LoadLibraryA Rust Implementation 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 use windows::Win32::System::Memory::*; use windows::Win32::System::Threading::*; use windows::Win32::Foundation::*; fn inject_dll(pid: u32, dll_path: &str) -> Result<(), String> { let dll_path_wide: Vec<u8> = dll_path.bytes() .chain(std::iter::once(0)) .collect(); // Step 1: Open target process unsafe { let process = OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD, None, pid, ).map_err(|e| format!("OpenProcess failed: {e}"))?; // Step 2: Allocate memory in target let remote_buf = VirtualAllocEx( process, None, dll_path_wide.len(), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, ); if remote_buf.is_null() { return Err("VirtualAllocEx failed".into()); } // Step 3: Write DLL path let mut written = 0usize; WriteProcessMemory( process, remote_buf, dll_path_wide.as_ptr() as *const _, dll_path_wide.len(), Some(&mut written), ).map_err(|e| format!("WriteProcessMemory failed: {e}"))?; // Step 4: Create remote thread let load_library = GetProcAddress( GetModuleHandleA(s!("kernel32"))?, s!("LoadLibraryA"), ); CreateRemoteThread( process, None, 0, Some(std::mem::transmute(load_library)), remote_buf, 0, None, ).map_err(|e| format!("CreateRemoteThread failed: {e}"))?; } Ok(()) } Cargo.toml 1 2 3 4 5 6 [dependencies] windows = { version = "0.58", features = [ "Win32_System_Memory", "Win32_System_Threading", "Win32_Foundation", ] } Detection & Defense Modern EDR solutions detect this technique through: ...