Skip to content

Commit 1279e69

Browse files
committed
Fix Unicorn Engine 1GB limit exit(): raise OSError instead (Fixes #2343)
This commit fixes #2343: an issue where `pwn checksec <binary>` would fail with a bogus error of: ``` $ pwn checksec /root/x/bin/main Could not allocate dynamic translator buffer ``` This actually comes from Unicorn Engine which tries to allocate a 1GB RWX mapping: ``` root@pwndbg:~# strace -e openat,mmap pwn checksec /root/x/bin/main 2>&1 | tail -n 10 openat(AT_FDCWD, "/usr/lib/python3/dist-packages/mpmath-0.0.0.egg-info/PKG-INFO", O_RDONLY|O_CLOEXEC) = 7 openat(AT_FDCWD, "/usr/local/lib/python3.10/dist-packages/unicorn/lib/libunicorn.so.2", O_RDONLY|O_CLOEXEC) = 7 mmap(NULL, 22447520, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 7, 0) = 0x7f2604f9d000 mmap(0x7f2605339000, 13496320, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 7, 0x39c000) = 0x7f2605339000 mmap(0x7f2606018000, 3039232, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 7, 0x107b000) = 0x7f2606018000 mmap(0x7f26062fe000, 1601536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 7, 0x1360000) = 0x7f26062fe000 mmap(0x7f2606485000, 525728, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2606485000 mmap(NULL, 1073741824, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) Could not allocate dynamic translator buffer +++ exited with 1 +++ ``` ...and if it fails, it calls `exit()`. This can be seen in Unicorn Engine code: https://github.com/unicorn-engine/unicorn/blob/56f3bdedb42d26bee1532cc01baf5eaf44a9aa23/qemu/accel/tcg/translate-all.c#L960-L963 This issue has been reported to Unicorn Engine in unicorn-engine/unicorn#1766 but since it hasn't been fixed, this commit applies a workaround for it.
1 parent b2cba03 commit 1279e69

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

pwnlib/elf/plt.py

+21
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,30 @@ def emulate_plt_instructions(elf, got, address, data, targets):
5353

5454
return rv
5555

56+
57+
def __ensure_memory_to_run_unicorn():
58+
"""
59+
Check if there is enough memory to run Unicorn Engine.
60+
Unicorn Engine requires 1GB of memory to run, if there isn't enough memory it calls exit(1).
61+
62+
This is a bug in Unicorn Engine, see: https://github.com/unicorn-engine/unicorn/issues/1766
63+
"""
64+
try:
65+
from mmap import mmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_READ, PROT_WRITE
66+
67+
mm = mmap(
68+
-1, 1024 * 1024 * 1024, MAP_PRIVATE | MAP_ANON, PROT_WRITE | PROT_READ | PROT_EXEC
69+
)
70+
mm.close()
71+
except OSError:
72+
raise OSError("Cannot allocate 1GB memory to run Unicorn Engine")
73+
74+
5675
def prepare_unicorn_and_context(elf, got, address, data):
5776
import unicorn as U
5877

78+
__ensure_memory_to_run_unicorn()
79+
5980
# Instantiate the emulator with the correct arguments for the current
6081
# architecutre.
6182
arch = {

0 commit comments

Comments
 (0)