Hi there đź‘‹

Welcome to my blog site. Thank you for coming.

Understanding ARM dissassembly Pt. 2

Introduction I had some confusion over the semantic of the word “disassembly”. So this is the next part to make up for that. For more details on the board I’m operating on, please refer to part 1 and the manual repo. main.c #define STM32F103xB #include "stm32f1xx.h" void delay(volatile uint32_t count) { while(count--); } int main(void) { // Enable GPIOC clock RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // Configure PC13 as output GPIOC->CRH = (GPIOC->CRH & ~0xFF000000) | 0x33000000; while(1) { GPIOC->ODR ^= (1 << 13); // Toggle delay(2000000); } } Binary Ninja Decompiled Output 08000000 void delay(uint32_t volatile count) __pure 08000000 { 08000000 uint32_t var_c = count; 08000012 uint32_t i; 08000012 08000012 do 08000012 { 0800000a i = var_c; 0800000e var_c = i - 1; 08000012 } while (i); 08000000 } 08000020 void main() __noreturn 08000020 { 08000020 *(uint32_t*)0x40021018 |= 0x10; 0800003e *(uint32_t*)0x40011004 = ( 0800003e *(uint32_t*)0x40011004 & 0xffffff) 0800003e | 0x33000000; 0800003e 0800004a while (true) 0800004a *(uint32_t*)0x4001100c ^= 0x2000; 08000020 } // Literal pool (constants stored in flash) 08000058 int32_t data_8000058 = 0x40021000 // RCC base 0800005c int32_t data_800005c = 0x40011000 // GPIOC base 08000060 int32_t data_8000060 = 0x1e8480 // 2000000 decimal Disassembly 08000000 void delay(uint32_t volatile count) __pure 08000000 80b4 push {r7} {__saved_r7} ; save r7 (frame pointer) 08000002 83b0 sub sp, #0xc ; allocate 12 bytes stack 08000004 00af add r7, sp, #0 {var_10} ; sp = r7 08000006 7860 str r0, [r7, #4] {var_c} ; store count at var_c 08000008 00bf nop 0800000a 7b68 ldr r3, [r7, #4] {var_c} ; r3 = var_c (current count) 0800000c 5a1e subs r2, r3, #1 ; r2 = r3 - 1 0800000e 7a60 str r2, [r7, #4] {var_c} ; r2 = var_c 08000010 002b cmp r3, #0 ; compare r3 to 0 08000012 fad1 bne #0x800000a ; "Branch to <address> if Not Equal" 08000014 00bf nop 08000016 00bf nop 08000018 0c37 adds r7, #0xc {__saved_r7} ; r7 += 12 0800001a bd46 mov sp, r7 ; sp = r7 (deallocate) 0800001c 80bc pop {r7} {__saved_r7} ; pop out of stack 0800001e 7047 bx lr ; return 08000020 void main() __noreturn 08000020 80b5 push {r7, lr} {var_4} {var_8} ; save frame pointer + ret addr as var_4 + var_8 08000022 00af add r7, sp, #0 {var_8} ; frame ptr ;Enable GPIOC clock ;RCC->APB2ENR |= RCC_APB2ENR_IOPCEN 08000024 0c4b ldr r3, [pc, #0x30] {data_8000058} {0x40021000} ; r3 = 0x40021000 (RCC base) 08000026 9b69 ldr r3, [r3, #0x18] {0x40021018} ; r3 = RCC->APB2ENR 08000028 0b4a ldr r2, [pc, #0x2c] {data_8000058} {0x40021000} ; r2 = 0x40021000 0800002a 43f01003 orr r3, r3, #0x10 ; Set bit 4 (IOCPEN) 0800002e 9361 str r3, [r2, #0x18] {0x40021018} ; Store r3 = r2 ;Config PC13 as output ;GPIOC->CRH = (GPIOC->CRH & ~0xFF000000) | 0x33000000 ;*(uint32_t*)0x40011004 = (*(uint32_t*)0x40011004 & 0xffffff) | 0x33000000; 08000030 0a4b ldr r3, [pc, #0x28] {data_800005c} {0x40011000} 08000032 5b68 ldr r3, [r3, #4] {0x40011004} 08000034 23f07f43 bic r3, r3, #0xff000000 08000038 084a ldr r2, [pc, #0x20] {data_800005c} {0x40011000} 0800003a 43f04c53 orr r3, r3, #0x33000000 0800003e 5360 str r3, [r2, #4] {0x40011004} ;GPIOC->ODR ^= (1 << 13) 08000040 064b ldr r3, [pc, #0x18] {data_800005c} {0x40011000} 08000042 db68 ldr r3, [r3, #0xc] {0x4001100c} 08000044 054a ldr r2, [pc, #0x14] {data_800005c} {0x40011000} 08000046 83f40053 eor r3, r3, #0x2000 0800004a d360 str r3, [r2, #0xc] {0x4001100c} ;delay 0800004c 0448 ldr r0, [pc, #0x10] {0x1e8480} {data_8000060} ;r0 = 0x1e8480 (2000000) 0800004e fff7d7ff bl #delay ;delay(2000000) 08000052 00bf nop 08000054 f4e7 b #0x8000040 ;Jump back to loop's start point 08000056 00 bf ;nop .. 08000058 int32_t data_8000058 = 0x40021000 ; RCC base 0800005c int32_t data_800005c = 0x40011000 ; GPIOC base 08000060 int32_t data_8000060 = 0x1e8480 ; decimal of 2000000 (2 sec) Processor core registers The variables’ names make more sense when you read the figure below. ...

HackTheBox's Cyber Apocalypse 2026 - Hardware

Disclaimer: This write-up will be a bit brief. I will comeback to actually finish this write-up later. Ughh, should have written it when I have just finished:( Cadence in the cord Description: With the Brine Signet shattered, every house hunts whatever might make its story law. Lady Seralyne — the Velvet Spider of Suncourt — sells what she claims is the dragon’s true note: not the lost thing itself, only a counterfeit cadence arranged to be believed, and a wavering house is ready to buy it as proof its claim rings true. We cut one of her sendings from the wire first. Read the pleasant words; then attend to the silences between them, and expose the forgery she is truly selling. ...

HackTheBox's Sherlock 2026 Write-up

Honestly, it recently feels sooooo boring writing a CTF challenge write-up. You know, with the rise of AI, doing all of these is kinda pointless now. Well, at least luckily, I’m a project-person. 1 Which Win32 structure defines the format of the buffer returned by the Lua script when monitoring directory changes? (string) - FILE_NOTIFY_INFORMATION Which Win32 API is used by the Lua script to send an HTTP request to the remote server? (string) - WinHttpSendRequest ...

Basic Baremetal STM32 Build and Flash

I forgot how did I compile all of that in those two stm32 posts, lol. The post will be very brief because this one is just a quick guide for me. I was kinda panic when I realized that I couldn’t quite recall what I have written myself… Full Pre-requisites sudo pacman -S arm-none-eabi-gcc gdb qemu-system-arm openocd stlink Compile ELF arm-none-eabi-gcc \ -mcpu=cortex-m3 \ -mthumb \ -mfloat-abi=soft \ -nostdlib \ -ffreestanding \ -Isrc -Iinc \ -T stm32f103c8t6.ld \ -Wl,-Map=build/blink.map \ -Wl,--gc-sections \ -Wl,--print-memory-usage \ src/vectors.c src/main.c \ -o build/blink.elf Convert to .bin arm-none-eabi-objcopy -O binary build/blink.elf build/blink.bin Since st-flash and QEMU expect raw binary. ...

Sherlock - Telly writeup

This post today will be about Telly - a HackTheBox Sherlock about the shiny new vulnerability of Telnet where it grants you sudo from userspace, in a pretty trivial manner. I will do a walkthrough the tasks in Sherlock first, then we will go on how this particular CVE works. Scenario You are a Junior DFIR Analyst at an MSSP that provides continuous monitoring and DFIR services to SMBs. Your supervisor has tasked you with analyzing network telemetry from a compromised backup server. A DLP solution flagged a possible data exfiltration attempt from this server. According to the IT team, this server wasn’t very busy and was sometimes used to store backups. ...

Sherlock - MidnightCrash writeup

Forewords Ah yes, finally, some Linux forensics tasks. Though, this one should have been on the difficulty level of easy, not medium (in my opinion of course, but don’t listen to this linux addict ;)) The most difficult part of this sherlock, in my opinion, is to figure out which tool would you need to read the kdump file, and henceforth, how to use crash. Introduction and Scenario A production server crashed unexpectedly and rebooted. The crash happened at a strange time, and we doubt it was a simple hardware fault. A kernel crash dump was captured. Your mission is to analyze it to find the real cause of the crash and determine if any other suspicious activity was present on the system. ...

Sherlock - Reaper writeup

This is one of the HackTheBox’s Sherlock - Reaper. It’s also one of the more terrible and sloppy write-up of mine, I don’t recommend you reading this unless there really is no other choice. Scenario Our SIEM alerted us to a suspicious logon event which needs to be looked at immediately. The alert details were that the IP Address and the Source Workstation name were a mismatch. You are provided a network capture and event logs from the surrounding time around the incident timeframe. Corelate the given evidence and report back to your SOC Manager. ...

Understanding ARM dissassembly

Introduction When you compile C code for an ARM microcontroller, the compiler translates your high-level code into machine instructions. Reverse engineering tools like Binary Ninja, Ghidra, radare2, etc. can decompile those instructions back into pseudo-C code. This guide shows you how to read that decompiled output and understand what’s happening at the hardware level. The Example: STM32 LED Blink We’ll use a simple LED blink program for an STM32F103xx (ARM Cortex-M3) microcontroller, that I have published in another repo: https://github.com/Flock137/stm32_blinky_baremetal ...

How to recover deleted files on usb or memory card

TLDR Stop using both the usb and memory card at once. Else, it will be next to impossible to recover anything back, since the data cells got overwritten, instead of just being “unlisted”. On Window (Linux), you can just install Recuva (extundelete or fatcat) for free and point the app to your usb or memory card, you’re welcome. However, I would still prefer a more sure-fire way to preserve my data, hence the blog. ...

Snyk's Fetch-the-flag Write-up (Forensics)

Void Step How many decoy hosts are randomized in this recon evasion technique Answer: 12 In Wireshark filter: (tcp.flags.syn == 1 && tcp.flags.ack == 0 ) && (ip.dst == 192.168.1.27) Explaination: Destination IP is found through manual inspection. For faster port scanning, we (or the attacker) perform the half-open scan, where SYN=1, ACK=0 (means: send only, no need response). Go to Statistics > Endpoints > IPv4, count the addresses, then minus 1 (the destination address, which we need to exclude). ...