Skip to content

Instantly share code, notes, and snippets.

@decagondev
Last active August 26, 2025 15:38
Show Gist options
  • Select an option

  • Save decagondev/1401228eebd6faea4bab3c592c0941dd to your computer and use it in GitHub Desktop.

Select an option

Save decagondev/1401228eebd6faea4bab3c592c0941dd to your computer and use it in GitHub Desktop.

Detailed Assembly Code Breakdown for C Program

This Markdown file provides an in-depth breakdown of three assembly functions extracted from an ELF file, representing a C program that takes user input, checks it against a computed value (derived from initial constants), and outputs a success or failure message. The messages are encoded using a ROT-3 cipher (subtract 3 from each character byte), and the shift function decodes and prints them. The analysis includes detailed line-by-line explanations, assembly code snippets, extrapolated C-like pseudocode, and logic flow represented in Mermaid diagrams.

Overview

  • Program Logic: The main function prompts the user, reads an integer input, computes a target value (90 + 492 = 582, then 582 squared = 338724), and calls test with the input and target. The test function compares them and calls shift on the appropriate encoded string address. The shift function decodes the string in place by subtracting 3 from each byte and then prints it using printf.
  • Key Addresses:
    • Prompt strings: Likely at 0x8048610 and 0x8048629 (e.g., "Enter password:" and similar).
    • Scanf format: At 0x8048634 (likely "%d").
    • Failure string (encoded): At 0x80485ec ("Lqydolg#Sdvvzrug$").
    • Success string (encoded): At 0x80485fe ("Sdvvzrug#RN$$$#='").
  • Assumptions: Based on x86 assembly (32-bit), strings are in .data section (writable). User input is an integer compared directly.

1. Main Function (<main>)

  • Address: 08048498

  • Purpose: Sets up the environment, displays prompts, reads user input as an integer, computes the target value, calls test for validation, and exits.

  • Detailed Breakdown (Line-by-Line):

    • 8048498: 55 push ebp: Pushes the base pointer to save the caller's stack frame.
    • 8048499: 89 e5 mov ebp,esp: Sets the base pointer to the current stack pointer, establishing the local stack frame.
    • 804849b: 83 ec 18 sub esp,0x18: Allocates 24 bytes on the stack for local variables.
    • 804849e: 83 e4 f0 and esp,0xfffffff0: Aligns the stack pointer to a 16-byte boundary for optimization/SSE.
    • 80484a1: b8 00 00 00 00 mov eax,0x0: Loads 0 into EAX (start of dynamic stack allocation calculation).
    • 80484a6: 83 c0 0f add eax,0xf: Adds 15 to EAX.
    • 80484a9: 83 c0 0f add eax,0xf: Adds another 15 (total 30, for rounding up).
    • 80484ac: c1 e8 04 shr eax,0x4: Shifts right by 4 (divides by 16).
    • 80484af: c1 e0 04 shl eax,0x4: Shifts left by 4 (multiplies by 16, rounding to nearest 16-byte multiple).
    • 80484b2: 29 c4 sub esp,eax: Subtracts the calculated value from ESP to allocate aligned space.
    • 80484b4: c7 04 24 10 86 04 08 mov DWORD PTR [esp],0x8048610: Loads the first prompt string address onto the stack.
    • 80484bb: e8 90 fe ff ff call 8048350 <printf@plt>: Calls printf to display the first prompt.
    • 80484c0: c7 04 24 29 86 04 08 mov DWORD PTR [esp],0x8048629: Loads the second prompt string address.
    • 80484c7: e8 84 fe ff ff call 8048350 <printf@plt>: Calls printf for the second prompt.
    • 80484cc: 8d 45 fc lea eax,[ebp-0x4]: Loads the address of a local variable (input buffer) into EAX.
    • 80484cf: 89 44 24 04 mov DWORD PTR [esp+0x4],eax: Pushes the input buffer address as the second argument.
    • 80484d3: c7 04 24 34 86 04 08 mov DWORD PTR [esp],0x8048634: Pushes the format string address ("%d").
    • 80484da: e8 51 fe ff ff call 8048330 <scanf@plt>: Calls scanf to read the integer input.
    • 80484df: c7 45 f8 5a 00 00 00 mov DWORD PTR [ebp-0x8],0x5a: Sets a local variable to 90 (0x5a).
    • 80484e6: c7 45 f4 ec 01 00 00 mov DWORD PTR [ebp-0xc],0x1ec: Sets another to 492 (0x1ec).
    • 80484ed: 8b 55 f4 mov edx,DWORD PTR [ebp-0xc]: Loads 492 into EDX.
    • 80484f0: 8d 45 f8 lea eax,[ebp-0x8]: Loads address of the first variable.
    • 80484f3: 01 10 add DWORD PTR [eax],edx: Adds 492 to 90 (result: 582 / 0x246).
    • 80484f5: 8b 45 f8 mov eax,DWORD PTR [ebp-0x8]: Loads 582 into EAX.
    • 80484f8: 0f af 45 f8 imul eax,DWORD PTR [ebp-0x8]: Multiplies EAX by itself (582 * 582 = 338724 / 0x52d04).
    • 80484fc: 89 45 f4 mov DWORD PTR [ebp-0xc],eax: Stores the squared result.
    • 80484ff: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc]: Loads the target into EAX.
    • 8048502: 89 44 24 04 mov DWORD PTR [esp+0x4],eax: Pushes target as second argument.
    • 8048506: 8b 45 fc mov eax,DWORD PTR [ebp-0x4]: Loads user input.
    • 8048509: 89 04 24 mov DWORD PTR [esp],eax: Pushes input as first argument.
    • 804850c: e8 5d ff ff ff call 804846e <test>: Calls the test function.
    • 8048511: b8 00 00 00 00 mov eax,0x0: Sets return value to 0.
    • 8048516: c9 leave: Restores stack frame.
    • 8048517: c3 ret: Returns from main.
    • Padding nops (8048518 to 804851f): No-op instructions for alignment.
  • Assembly Code Snippet:

    08048498 <main>:
     8048498:	55                   	push   ebp
     8048499:	89 e5                	mov    ebp,esp
     804849b:	83 ec 18             	sub    esp,0x18
     804849e:	83 e4 f0             	and    esp,0xfffffff0
     80484a1:	b8 00 00 00 00       	mov    eax,0x0
     80484a6:	83 c0 0f             	add    eax,0xf
     80484a9:	83 c0 0f             	add    eax,0xf
     80484ac:	c1 e8 04             	shr    eax,0x4
     80484af:	c1 e0 04             	shl    eax,0x4
     80484b2:	29 c4                	sub    esp,eax
     80484b4:	c7 04 24 10 86 04 08 	mov    DWORD PTR [esp],0x8048610
     80484bb:	e8 90 fe ff ff       	call   8048350 <printf@plt>
     80484c0:	c7 04 24 29 86 04 08 	mov    DWORD PTR [esp],0x8048629
     80484c7:	e8 84 fe ff ff       	call   8048350 <printf@plt>
     80484cc:	8d 45 fc             	lea    eax,[ebp-0x4]
     80484cf:	89 44 24 04          	mov    DWORD PTR [esp+0x4],eax
     80484d3:	c7 04 24 34 86 04 08 	mov    DWORD PTR [esp],0x8048634
     80484da:	e8 51 fe ff ff       	call   8048330 <scanf@plt>
     80484df:	c7 45 f8 5a 00 00 00 	mov    DWORD PTR [ebp-0x8],0x5a
     80484e6:	c7 45 f4 ec 01 00 00 	mov    DWORD PTR [ebp-0xc],0x1ec
     80484ed:	8b 55 f4             	mov    edx,DWORD PTR [ebp-0xc]
     80484f0:	8d 45 f8             	lea    eax,[ebp-0x8]
     80484f3:	01 10                	add    DWORD PTR [eax],edx
     80484f5:	8b 45 f8             	mov    eax,DWORD PTR [ebp-0x8]
     80484f8:	0f af 45 f8          	imul   eax,DWORD PTR [ebp-0x8]
     80484fc:	89 45 f4             	mov    DWORD PTR [ebp-0xc],eax
     80484ff:	8b 45 f4             	mov    eax,DWORD PTR [ebp-0xc]
     8048502:	89 44 24 04          	mov    DWORD PTR [esp+0x4],eax
     8048506:	8b 45 fc             	mov    eax,DWORD PTR [ebp-0x4]
     8048509:	89 04 24             	mov    DWORD PTR [esp],eax
     804850c:	e8 5d ff ff ff       	call   804846e <test>
     8048511:	b8 00 00 00 00       	mov    eax,0x0
     8048516:	c9                   	leave  
     8048517:	c3                   	ret    
    
  • C-like Pseudocode:

    int main() {
        int input;
        int var1 = 90;  // 0x5a
        int var2 = 492; // 0x1ec
        printf("Prompt string 1\n");  // Address 0x8048610
        printf("Prompt string 2\n");  // Address 0x8048629
        scanf("%d", &input);         // Address 0x8048634 for format
        var1 += var2;                // 582
        var2 = var1 * var1;          // 338724
        test(input, var2);
        return 0;
    }
  • Mermaid Diagram (Logic Flow):

    graph TD
        A[Start Main] --> B[Setup Stack Frame & Align]
        B --> C[Allocate Dynamic Stack Space]
        C --> D[Print Prompt 1]
        D --> E[Print Prompt 2]
        E --> F[Read User Input via scanf]
        F --> G[Initialize var1=90, var2=492]
        G --> H[Add: var1 += var2  // 582]
        H --> I[Square: var2 = var1 * var1  // 338724]
        I --> J[Call test: input, var2]
        J --> K[Return 0]
        K --> L[End Main]
    
    Loading

2. Test Function (<test>)

  • Address: 0804846e

  • Purpose: Compares the user input with the target value. If equal, calls shift on the success string (decodes and prints it); otherwise, on the failure string.

  • Detailed Breakdown (Line-by-Line):

    • 804846e: 55 push ebp: Saves the caller's base pointer.
    • 804846f: 89 e5 mov ebp,esp: Establishes the local stack frame.
    • 8048471: 83 ec 08 sub esp,0x8: Allocates 8 bytes on the stack (unused, possibly for alignment).
    • 8048474: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]: Loads user input (first argument) into EAX.
    • 8048477: 3b 45 0c cmp eax,DWORD PTR [ebp+0xc]: Compares input with target (second argument).
    • 804847a: 74 0e je 804848a: If equal, jumps to success branch.
    • 804847c: c7 04 24 ec 85 04 08 mov DWORD PTR [esp],0x80485ec: (Failure branch) Loads failure string address ("Lqydolg#Sdvvzrug$") onto stack.
    • 8048483: e8 8c ff ff ff call 8048414 <shift>: Calls shift to decode and print failure string.
    • 8048488: eb 0c jmp 8048496: Jumps to end.
    • 804848a: c7 04 24 fe 85 04 08 mov DWORD PTR [esp],0x80485fe: (Success branch) Loads success string address ("Sdvvzrug#RN$$$#=,").
    • 8048491: e8 7e ff ff ff call 8048414 <shift>: Calls shift to decode and print success string.
    • 8048496: c9 leave: Restores stack frame.
    • 8048497: c3 ret: Returns from test.
  • Assembly Code Snippet:

    0804846e <test>:
     804846e:	55                   	push   ebp
     804846f:	89 e5                	mov    ebp,esp
     8048471:	83 ec 08             	sub    esp,0x8
     8048474:	8b 45 08             	mov    eax,DWORD PTR [ebp+0x8]
     8048477:	3b 45 0c             	cmp    eax,DWORD PTR [ebp+0xc]
     804847a:	74 0e                	je     804848a <test+0x1c>
     804847c:	c7 04 24 ec 85 04 08 	mov    DWORD PTR [esp],0x80485ec
     8048483:	e8 8c ff ff ff       	call   8048414 <shift>
     8048488:	eb 0c                	jmp    8048496 <test+0x28>
     804848a:	c7 04 24 fe 85 04 08 	mov    DWORD PTR [esp],0x80485fe
     8048491:	e8 7e ff ff ff       	call   8048414 <shift>
     8048496:	c9                   	leave  
     8048497:	c3                   	ret    
    
  • C-like Pseudocode:

    void test(int input, int target) {
        if (input == target) {
            shift(0x80485fe);  // Decode and print "Sdvvzrug#RN$$$#=," -> "Password OK :);"
        } else {
            shift(0x80485ec);  // Decode and print "Lqydolg#Sdvvzrug$" -> "Invalid Password!"
        }
    }
  • Mermaid Diagram (Logic Flow):

    graph TD
        A[Start Test] --> B[Setup Stack Frame]
        B --> C[Load Input into EAX]
        C --> D[Compare Input == Target]
        D -->|Equal| E[Load Success String Address: 0x80485fe]
        E --> F[Call shift on Sdvvzrug#RN$$$#=']
        F --> I[End Test]
        D -->|Not Equal| G[Load Failure String Address: 0x80485ec]
        G --> H[Call shift on Lqydolg#Sdvvzrug$]
        H --> I[End Test]
    
    Loading

3. Shift Function (<shift>)

  • Address: 08048414

  • Purpose: Takes a string pointer, decodes it in place by subtracting 3 from each character (ROT-3 decode), then prints the decoded string using printf.

  • Detailed Breakdown (Line-by-Line):

    • 8048414: 55 push ebp: Saves base pointer.
    • 8048415: 89 e5 mov ebp,esp: Establishes frame.
    • 8048417: 81 ec 98 00 00 00 sub esp,0x98: Allocates 152 bytes (large for safety, possibly buffer).
    • 804841d: c7 45 84 00 00 00 00 mov DWORD PTR [ebp-0x7c],0x0: Initializes loop index i = 0.
    • 8048424: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]: Loads string pointer into EAX.
    • 8048427: 89 04 24 mov DWORD PTR [esp],eax: Pushes string for strlen.
    • 804842a: e8 11 ff ff ff call 8048340 <strlen@plt>: Calls strlen, result in EAX.
    • 804842f: 89 45 88 mov DWORD PTR [ebp-0x78],eax: Stores length in [ebp-0x78].
    • 8048432: 8b 45 84 mov eax,DWORD PTR [ebp-0x7c]: Loads i into EAX.
    • 8048435: 3b 45 88 cmp eax,DWORD PTR [ebp-0x78]: Compares i < len.
    • 8048438: 73 18 jae 8048452: If i >= len, jumps to end of loop (note: image shows 73 for jae).
    • 804843a: 8b 55 84 mov edx,DWORD PTR [ebp-0x7c]: Loads i into EDX.
    • 804843d: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]: Loads string base.
    • 8048440: 01 d0 add eax,edx: Computes str + i.
    • 8048442: 0f b6 00 movzx eax,BYTE PTR [eax]: Loads byte at str[i] (zero-extended).
    • 8048445: 2c 03 sub al,0x3: Subtracts 3 (decode).
    • 8048447: 88 00 mov BYTE PTR [eax],al: Stores back the decoded byte (note: likely should be mov BYTE PTR [edx+eax], al due to addressing error).
    • 8048449: 83 45 84 01 add DWORD PTR [ebp-0x7c],0x1: Increments i.
    • 804844d: eb d5 jmp 8048424: Jumps back to loop start.
    • 804844f: 90 nop: Alignment nop.
    • 8048450: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]: Loads decoded string pointer.
    • 8048453: 89 04 24 mov DWORD PTR [esp],eax: Pushes for printf.
    • 8048456: e8 f5 fe ff ff call 8048350 <printf@plt>: Calls printf to output the string.
    • 804845b: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]: Loads string pointer (return value).
    • 804845e: c9 leave: Restores frame.
    • 804845f: c3 ret: Returns the string pointer.
  • Assembly Code Snippet:

    08048414 <shift>:
     8048414:	55                   	push   ebp
     8048415:	89 e5                	mov    ebp,esp
     8048417:	81 ec 98 00 00 00    	sub    esp,0x98
     804841d:	c7 45 84 00 00 00 00 	mov    DWORD PTR [ebp-0x7c],0x0
     8048424:	8b 45 08             	mov    eax,DWORD PTR [ebp+0x8]
     8048427:	89 04 24             	mov    DWORD PTR [esp],eax
     804842a:	e8 11 ff ff ff       	call   8048340 <strlen@plt>
     804842f:	89 45 88             	mov    DWORD PTR [ebp-0x78],eax
     8048432:	8b 45 84             	mov    eax,DWORD PTR [ebp-0x7c]
     8048435:	3b 45 88             	cmp    eax,DWORD PTR [ebp-0x78]
     8048438:	73 18                	jae    8048452 <shift+0x3e>
     804843a:	8b 55 84             	mov    edx,DWORD PTR [ebp-0x7c]
     804843d:	8b 45 08             	mov    eax,DWORD PTR [ebp+0x8]
     8048440:	01 d0                	add    eax,edx
     8048442:	0f b6 00             	movzx  eax,BYTE PTR [eax]
     8048445:	2c 03                	sub    al,0x3
     8048447:	88 00                	mov    BYTE PTR [eax],al
     8048449:	83 45 84 01          	add    DWORD PTR [ebp-0x7c],0x1
     804844d:	eb d5                	jmp    8048424 <shift+0x10>
     804844f:	90                   	nop
     8048450:	8b 45 08             	mov    eax,DWORD PTR [ebp+0x8]
     8048453:	89 04 24             	mov    DWORD PTR [esp],eax
     8048456:	e8 f5 fe ff ff       	call   8048350 <printf@plt>
     804845b:	8b 45 08             	mov    eax,DWORD PTR [ebp+0x8]
     804845e:	c9                   	leave  
     804845f:	c3                   	ret    
    
  • C-like Pseudocode:

    char* shift(char* str) {
        int len = strlen(str);
        for (int i = 0; i < len; i++) {
            str[i] -= 3;  // ROT-3 decode (e.g., "Lqydolg#Sdvvzrug$" -> "Invalid#Password$")
        }                 // or "Sdvvzrug#RN$$$#=" -> "Password#OK$$$#;"
        printf("%s\n", str);
        return str;
    }
  • Mermaid Diagram (Logic Flow):

    graph TD
        A[Start Shift] --> B[Setup Stack Frame]
        B --> C[Initialize i = 0]
        C --> D[Compute len = strlen: str]
        D --> E[Compare i < len]
        E -->|Yes| F[Load str at i]
        F --> G[Subtract 3 from str at i]
        G --> H[Store back to str at i]
        H --> I[Increment i]
        I --> D[Loop Back]
        E -->|No| J[Load Decoded str]
        J --> K[Call printf on str]
        K --> L[Return str Pointer]
        L --> M[End Shift]
    
    Loading

Additional Notes

  • Security Implications: Modifying strings in place assumes a writable data section; in modern systems, this might trigger protections (e.g., W^X).
  • Decoding Example:
    • "Lqydolg#Sdvvzrug$" (0x80485ec) decodes to "Invalid#Password$" (L-3=I, q-3=n, etc.).
    • "Sdvvzrug#RN$$$#=" (0x80485fe) decodes to "Password#OK$$$#;" (S-3=P, d-3=a, etc.).
  • Target Value: User must input 338724 for success.
  • Potential Improvements: In C, use const char* for strings, but here modification is intentional for obfuscation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment