mirror of https://github.com/pwndbg/pwndbg.git
fix: mprotect command and add tests for it
Turns out the mprotect command didn't ever work, as it was amd64 only, but used x86 syscall numbers to call mprotect. I have refactored the command to use shellcraft to generate the shellcode that calls mprotect. I have also unit-tested this command.pull/1166/head
parent
d2ba9955b5
commit
9e84c18c44
@ -0,0 +1,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//
|
||||
// pwnlib.asm.asm(pwnlib.shellcraft.amd64.linux.echo("mprotect_ok"), arch='amd64').hex()
|
||||
uint8_t func[] = {
|
||||
0x36, 0x38, 0x35, 0x65, 0x36, 0x65, 0x36, 0x61, 0x30, 0x31, 0x38, 0x31, 0x33, 0x34, 0x32, 0x34, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x34, 0x38, 0x62, 0x38, 0x36, 0x64, 0x37, 0x30, 0x37, 0x32, 0x36, 0x66, 0x37, 0x34, 0x36, 0x35, 0x36, 0x33, 0x37, 0x34, 0x35, 0x30, 0x36, 0x61, 0x30, 0x31, 0x35, 0x38, 0x36, 0x61, 0x30, 0x31, 0x35, 0x66, 0x36, 0x61, 0x30, 0x62, 0x35, 0x61, 0x34, 0x38, 0x38, 0x39, 0x65, 0x36, 0x30, 0x66, 0x30, 0x35, 0x33, 0x31, 0x66, 0x66, 0x36, 0x61, 0x33, 0x63, 0x35, 0x38, 0x30, 0x66, 0x30, 0x35
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
void (*f)() = (void (*)())func;
|
||||
printf("ptr = %p", f);
|
||||
// f();
|
||||
return 1;
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
import gdb
|
||||
|
||||
import pwndbg
|
||||
import tests
|
||||
|
||||
MPROTECT_BINARY = tests.binaries.get("mprotect.out")
|
||||
|
||||
def test_mprotect(start_binary):
|
||||
"""
|
||||
Tests mprotect command
|
||||
It will mark some memory as executable, then this binary will print "mprotect_ok"
|
||||
"""
|
||||
start_binary(MPROTECT_BINARY)
|
||||
|
||||
gdb.execute("starti")
|
||||
# get addr of func
|
||||
addr = int(gdb.parse_and_eval("&func"))
|
||||
addr_aligned = pwndbg.lib.memory.page_align(addr)
|
||||
|
||||
# sizeof
|
||||
size = int(gdb.parse_and_eval("sizeof(func)"))
|
||||
size_aligned = pwndbg.lib.memory.page_align(size)
|
||||
|
||||
vmmaps_before = gdb.execute("vmmap -x", to_string=True).splitlines()
|
||||
|
||||
# mark memory as executable
|
||||
gdb.execute("mprotect {} {} PROT_EXEC|PROT_READ|PROT_WRITE".format(hex(addr_aligned), pwndbg.lib.memory.PAGE_SIZE))
|
||||
|
||||
vmmaps_after = gdb.execute("vmmap -x", to_string=True).splitlines()
|
||||
|
||||
# expect vmmaps_after to be one element longer than vmmaps_before
|
||||
assert len(vmmaps_after) == len(vmmaps_before) + 1
|
||||
|
||||
# get the changed vmmap entry
|
||||
vmmap_entry = [x for x in vmmaps_after if x not in vmmaps_before][0]
|
||||
|
||||
assert vmmap_entry.split()[2] == "rwxp"
|
||||
|
||||
# continue execution
|
||||
gdb.execute("continue")
|
||||
|
||||
|
||||
|
||||
def test_cannot_run_mprotect_when_not_running(start_binary):
|
||||
|
||||
|
||||
# expect error message
|
||||
assert "mprotect: The program is not being run.\n" == gdb.execute("mprotect 0x0 0x1000 PROT_EXEC|PROT_READ|PROT_WRITE", to_string=True)
|
||||
Loading…
Reference in new issue