Open mewmew opened 6 years ago
This issue is likely something to do with pwntools. It appears that pwntools is attempting to assemble 32-bit assembly as 64-bit assembly. I can rewrite the binary on my test machine without encountering this bug, so there may be some issue with pwntools itself. However, the rewritten binary will not run for a few reasons.
Multiverse by default assumes the architecture is 32-bit x86. If you want to rewrite a 64-bit binary, you need to include the flag --arch x86-64
. However, the binary you are attempting to rewrite is a Position-Independent Executable (PIE). We do support Position-Independent Code (PIC), but only in libraries. This isn't an inherent limitation of our approach, but some limitations with the way we generate a final rewritten executable mean that we don't currently support the main executable being position-independent. That will require some extra engineering that hasn't been done yet. I apologize for any inconvenience this may cause.
Hi @utds3lab,
Thanks for the detailed explanation. Of course, there will always be edge cases, good to know that the PIE related one is not a design issue, but rather based on implementation time.
What version of pwntools do you have? I keep running into the operand type mismatch for
pop'` error also for 32-bit binaries.
u@x220 /u/bin> file /usr/bin/{jad,wine}
/usr/bin/jad: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.0.0, stripped, too many notes (256)
/usr/bin/wine: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a0030d47f13af4b7f865977133c4d1fa94793bb6, stripped
For 32-bit binary wine
: https://ufile.io/zyikp
u@x220 ~/D/g/s/g/m/multiverse> python2 ./multiverse.py --arch x86 /usr/bin/wine
Found .text
Writing as main binary
Base address: 0x7c000000
Generating mapping...
Starting disassembly...
Disassembly 0% complete...
Disassembly 10% complete...
[ERROR] There was an error running ['/usr/bin/as', '-64', '-o', '/tmp/pwn-asm-MDhWG2/step2', '/tmp/pwn-asm-MDhWG2/step1']:
It had the exitcode 1.
It had this on stdout:
/tmp/pwn-asm-MDhWG2/step1: Assembler messages:
/tmp/pwn-asm-MDhWG2/step1:7: Error: operand type mismatch for `pop'
[ERROR] An error occurred while assembling:
1: .section .shellcode,"awx"
2: .global _start
3: .global __start
4: _start:
5: __start:
6: .intel_syntax noprefix
7: pop eax
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 665, in asm
_run(assembler + ['-o', step2, step1])
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 383, in _run
log.error(msg)
File "/usr/lib/python2.7/site-packages/pwnlib/log.py", line 417, in error
raise PwnlibException(message % args)
PwnlibException: There was an error running ['/usr/bin/as', '-64', '-o', '/tmp/pwn-asm-MDhWG2/step2', '/tmp/pwn-asm-MDhWG2/step1']:
It had the exitcode 1.
It had this on stdout:
/tmp/pwn-asm-MDhWG2/step1: Assembler messages:
/tmp/pwn-asm-MDhWG2/step1:7: Error: operand type mismatch for `pop'
Traceback (most recent call last):
File "./multiverse.py", line 317, in <module>
rewriter.rewrite(args.filename,args.arch)
File "./multiverse.py", line 191, in rewrite
mapping = mapper.gen_mapping()
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/brute_force_mapper.py", line 53, in gen_mapping
newins = self.translator.translate_one(ins,None) #In this pass, the mapping is incomplete
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/x86_translator.py", line 24, in translate_one
return self.translate_ret(ins,mapping)
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/x86_translator.py", line 64, in translate_ret
code = asm(template_before)
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/x86_assembler.py", line 119, in asm
code+=_asm(line)
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/x86_assembler.py", line 28, in _asm
code = pwn.asm(text)
File "/usr/lib/python2.7/site-packages/pwnlib/context/__init__.py", line 1392, in setter
return function(*a)
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 710, in asm
log.exception("An error occurred while assembling:\n%s" % lines)
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 665, in asm
_run(assembler + ['-o', step2, step1])
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 383, in _run
log.error(msg)
File "/usr/lib/python2.7/site-packages/pwnlib/log.py", line 417, in error
raise PwnlibException(message % args)
pwnlib.exception.PwnlibException: There was an error running ['/usr/bin/as', '-64', '-o', '/tmp/pwn-asm-MDhWG2/step2', '/tmp/pwn-asm-MDhWG2/step1']:
It had the exitcode 1.
It had this on stdout:
/tmp/pwn-asm-MDhWG2/step1: Assembler messages:
/tmp/pwn-asm-MDhWG2/step1:7: Error: operand type mismatch for `pop'
And for 32-bit binary jad
: https://ufile.io/m8ijp
u@x220 ~/D/g/s/g/m/multiverse> python2 ./multiverse.py --arch x86 /usr/bin/jad
Found .text
binary does not contain plt
Writing as main binary
Base address: 0x8048000
Generating mapping...
Starting disassembly...
Disassembly 0% complete...
[ERROR] There was an error running ['/usr/bin/as', '-64', '-o', '/tmp/pwn-asm-lXz0Es/step2', '/tmp/pwn-asm-lXz0Es/step1']:
It had the exitcode 1.
It had this on stdout:
/tmp/pwn-asm-lXz0Es/step1: Assembler messages:
/tmp/pwn-asm-lXz0Es/step1:7: Error: operand type mismatch for `pop'
[ERROR] An error occurred while assembling:
1: .section .shellcode,"awx"
2: .global _start
3: .global __start
4: _start:
5: __start:
6: .intel_syntax noprefix
7: pop eax
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 665, in asm
_run(assembler + ['-o', step2, step1])
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 383, in _run
log.error(msg)
File "/usr/lib/python2.7/site-packages/pwnlib/log.py", line 417, in error
raise PwnlibException(message % args)
PwnlibException: There was an error running ['/usr/bin/as', '-64', '-o', '/tmp/pwn-asm-lXz0Es/step2', '/tmp/pwn-asm-lXz0Es/step1']:
It had the exitcode 1.
It had this on stdout:
/tmp/pwn-asm-lXz0Es/step1: Assembler messages:
/tmp/pwn-asm-lXz0Es/step1:7: Error: operand type mismatch for `pop'
Traceback (most recent call last):
File "./multiverse.py", line 317, in <module>
rewriter.rewrite(args.filename,args.arch)
File "./multiverse.py", line 191, in rewrite
mapping = mapper.gen_mapping()
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/brute_force_mapper.py", line 53, in gen_mapping
newins = self.translator.translate_one(ins,None) #In this pass, the mapping is incomplete
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/x86_translator.py", line 24, in translate_one
return self.translate_ret(ins,mapping)
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/x86_translator.py", line 64, in translate_ret
code = asm(template_before)
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/x86_assembler.py", line 119, in asm
code+=_asm(line)
File "/home/u/Desktop/go/src/github.com/mewbak/multiverse/x86_assembler.py", line 28, in _asm
code = pwn.asm(text)
File "/usr/lib/python2.7/site-packages/pwnlib/context/__init__.py", line 1392, in setter
return function(*a)
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 710, in asm
log.exception("An error occurred while assembling:\n%s" % lines)
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 665, in asm
_run(assembler + ['-o', step2, step1])
File "/usr/lib/python2.7/site-packages/pwnlib/asm.py", line 383, in _run
log.error(msg)
File "/usr/lib/python2.7/site-packages/pwnlib/log.py", line 417, in error
raise PwnlibException(message % args)
pwnlib.exception.PwnlibException: There was an error running ['/usr/bin/as', '-64', '-o', '/tmp/pwn-asm-lXz0Es/step2', '/tmp/pwn-asm-lXz0Es/step1']:
It had the exitcode 1.
It had this on stdout:
/tmp/pwn-asm-lXz0Es/step1: Assembler messages:
/tmp/pwn-asm-lXz0Es/step1:7: Error: operand type mismatch for `pop'
Cheers, /u
I have successfully run it with pwntools versions 2.2 and 3.12.0. Could you try the solution of adding the bits=32
option as was tried by @ehsmeng in this issue? It looks like they had a similar problem that was solved by this. Please let me know if this change works for you, and also what version of pwntools you are currently using.
For the records, I'm using pwntools version 3.12.0.
Applying the change to x86_assembler.py
as suggested by @ehsmeng worked better. Now multiverse was capable of rewriting the 32-bit jad
binary:
u@x220 ~/D/g/s/g/m/multiverse> python2 ./multiverse.py --arch x86 ./foo/jad
Found .text
binary does not contain plt
Writing as main binary
Base address: 0x8048000
Generating mapping...
Starting disassembly...
Disassembly 0% complete...
Disassembly 10% complete...
Disassembly 20% complete...
Disassembly 30% complete...
Disassembly 40% complete...
Disassembly 50% complete...
Disassembly 60% complete...
Disassembly 70% complete...
Disassembly 80% complete...
Disassembly 90% complete...
WARNING: silently converting "mov eax, word ptr [<number>]" to "mov eax, dword ptr [<number>]"
Disassembly 100% complete...
final offset for mapping is: 0x3c8c68
Generating new code...
Starting disassembly...
Disassembly 0% complete...
Disassembly 10% complete...
Disassembly 20% complete...
Disassembly 30% complete...
Disassembly 40% complete...
Disassembly 50% complete...
Disassembly 60% complete...
Disassembly 70% complete...
Disassembly 80% complete...
Disassembly 90% complete...
WARNING: silently converting "mov eax, word ptr [<number>]" to "mov eax, dword ptr [<number>]"
Disassembly 100% complete...
mapping is being placed at offset: 0x3c8c68
last address in mapping was 0x8119be0
just set global_flag value to 0x-4
66
72
last address in mapping was 0x8119be0
0x8119be0
code increase: 761%
lookup w/unknown mapping 66
lookup w/known mapping 66
new entry point: 0x93c8c13
new _start point: 0x9100c97
global lookup: 0x7000000
local lookup: 0x0
secondary local lookup: 0x8f
mapping offset: 0x3c8c68
length of new contents: 0x4
.text section too small to hold phdrs (or 32-bit binary); using other heuristics to relocate phdrs
WARNING elfmanip.relocate_phdrs :: All methods failed
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
However, the rewritten binary does not seem to work.
u@x220 ~/D/g/s/g/m/m/foo> ls -la ./jad-r
-rwxr-xr-x 1 u users 961576 May 17 03:28 ./jad-r*
u@x220 ~/D/g/s/g/m/m/foo> file ./jad-r
./jad-r: ERROR: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.0.0 error reading (Invalid argument)
u@x220 ~/D/g/s/g/m/m/foo> ./jad-r
fish: “./jad-r” terminated by signal SIGSEGV (Address boundary error)
A copy of jad-r
has been uploaded to https://ufile.io/ygbg3
Cheers, /u
Please refer to the README for some necessary details about rewriting and running binaries. The default settings require that you rewrite all the libraries of the binary as well. If you want to only rewrite the binary and not the libraries, you need to pass the --execonly flag.
Also, you need to run rewritten binaries with LD_BIND_NOW=1, as that environment variable tells the loader to not do lazy loading while a rewritten binary is running. Since we aren't rewriting the loader, it can redirect control flow to incorrect addresses unless we disable lazy loading.
I suggest getting the simplest64
or simplest32
test program working first, as getting it working is documented in the README.
Thanks for the info, I should have read up more in advance.
I checked the jad
binary, and it seems to be statically linked, so it should work?
I also tried running with LD_BIND_NOW=1 and --execonly, but got the same results:
[u@x220 multiverse]$ LD_BIND_NOW=1 python2 ./multiverse.py --arch=x86 --execonly foo/jad
Found .text
binary does not contain plt
Writing ONLY main binary, without support for rewritten .so files
Base address: 0x8048000
Generating mapping...
Starting disassembly...
Disassembly 0% complete...
Disassembly 10% complete...
Disassembly 20% complete...
Disassembly 30% complete...
Disassembly 40% complete...
Disassembly 50% complete...
Disassembly 60% complete...
Disassembly 70% complete...
Disassembly 80% complete...
Disassembly 90% complete...
WARNING: silently converting "mov eax, word ptr [<number>]" to "mov eax, dword ptr [<number>]"
Disassembly 100% complete...
final offset for mapping is: 0x3c8c95
Generating new code...
Starting disassembly...
Disassembly 0% complete...
Disassembly 10% complete...
Disassembly 20% complete...
Disassembly 30% complete...
Disassembly 40% complete...
Disassembly 50% complete...
Disassembly 60% complete...
Disassembly 70% complete...
Disassembly 80% complete...
Disassembly 90% complete...
WARNING: silently converting "mov eax, word ptr [<number>]" to "mov eax, dword ptr [<number>]"
Disassembly 100% complete...
mapping is being placed at offset: 0x3c8c95
last address in mapping was 0x8119be0
just set global_flag value to 0x-4
111
117
last address in mapping was 0x8119be0
0x8119be0
code increase: 761%
lookup w/unknown mapping 62
lookup w/known mapping 62
new entry point: 0x93c8c40
new _start point: 0x9100cc4
global lookup: 0x7000000
local lookup: 0x0
secondary local lookup: 0x3e
mapping offset: 0x3c8c95
length of new contents: 0x4
.text section too small to hold phdrs (or 32-bit binary); using other heuristics to relocate phdrs
WARNING elfmanip.relocate_phdrs :: All methods failed
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
[u@x220 foo]$ file jad-r
jad-r: ERROR: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.0.0 error reading (Invalid argument)
[u@x220 foo]$ ./jad-r
Segmentation fault (core dumped)
What am I missing?
EDIT: re-reading your post, I noticed that it is the rewritten binary I need to run with LD_LINK_NOW=1, not multiverse. Must have been an early morning :)
However, running the rewritten jad
with LD_LINK_NOW=1 results in a segfault all the same.
u@x220 ~/D/g/s/g/m/m/foo> /bin/bash
[u@x220 foo]$ LD_LINK_NOW=1 ./jad-r
Segmentation fault (core dumped)
Info from readelf:
[u@x220 foo]$ readelf -a jad-r
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x93c8c40
Start of program headers: 52 (bytes into file)
Start of section headers: 960776 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 3
Size of section headers: 40 (bytes)
Number of section headers: 24
Section header string table index: 19
readelf: Error: Reading 960 bytes extends past end of file for section headers
readelf: Error: Section headers are not available!
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0xd1be0 0xd1be0 R E 0x1000
LOAD 0x0d1be0 0x0811abe0 0x0811abe0 0x14c9c 0x1636c RW 0x1000
NOTE 0x000094 0x08048094 0x08048094 0x00020 0x00020 R 0x4
There is no dynamic section in this file.
Displaying notes found at file offset 0x00000094 with length 0x00000020:
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
The latest rewritten binary (jad-r
) is uploaded to https://ufile.io/6nrwa
I apologize for the delay, I have been travelling.
There is a problem with the elfmanip library. As you can tell from the output
ERROR elfmanip.add_segment :: Cannot add another section. Not enough room in the program headers to add another segment
elfmanip is having trouble inserting the segments that Multiverse needs for the binary to work. Check out this comment about why some binaries may not be successfully rewritten. This specific binary lacks many of the components that elfmanip uses for adding segments, unfortunately. Hopefully we can continue to improve elfmanip's capabilities in the future.
I apologize for the delay, I have been travelling.
No worries, and thanks for tracking this issue.
@utds3lab hello, I follow the readme file, but
$ LD_BIND_NOW=1 ./simplest64-r
Segmentation fault (core dumped)
could you give me some advice, thx !
On rev b90ffd6df1d1470bce097e5afb7172ba3cdb3b3a, the following error is output when running
python2 ./multiverse.py /usr/bin/true
I've uploaded a copy of the
true
command to https://ufile.io/nyh9cEDIT: note, the above download link is only valid for 30 days.