pwntools 0.1.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +96 -15
- data/Rakefile +8 -2
- data/lib/pwn.rb +10 -7
- data/lib/pwnlib/abi.rb +61 -0
- data/lib/pwnlib/asm.rb +357 -0
- data/lib/pwnlib/constants/constant.rb +19 -3
- data/lib/pwnlib/constants/constants.rb +46 -20
- data/lib/pwnlib/constants/linux/amd64.rb +32 -1
- data/lib/pwnlib/constants/linux/i386.rb +2 -0
- data/lib/pwnlib/context.rb +128 -27
- data/lib/pwnlib/dynelf.rb +122 -54
- data/lib/pwnlib/elf/elf.rb +340 -0
- data/lib/pwnlib/errors.rb +31 -0
- data/lib/pwnlib/ext/array.rb +2 -1
- data/lib/pwnlib/ext/helper.rb +6 -5
- data/lib/pwnlib/ext/integer.rb +2 -1
- data/lib/pwnlib/ext/string.rb +3 -2
- data/lib/pwnlib/logger.rb +245 -0
- data/lib/pwnlib/memleak.rb +59 -29
- data/lib/pwnlib/pwn.rb +27 -9
- data/lib/pwnlib/reg_sort.rb +109 -110
- data/lib/pwnlib/runner.rb +53 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/common.rb +16 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/infloop.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/memcpy.rb +35 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/mov.rb +131 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/nop.rb +18 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/popad.rb +28 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr.rb +66 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr_array.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/ret.rb +33 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/setregs.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/cat.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/execve.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/exit.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/linux.rb +16 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/ls.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/open.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/sh.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/sleep.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/syscall.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/helper.rb +115 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/common.rb +16 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/infloop.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/memcpy.rb +34 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/mov.rb +93 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/nop.rb +18 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/pushstr.rb +41 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/pushstr_array.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/setregs.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/cat.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/execve.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/exit.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/linux.rb +16 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/ls.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/open.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/sh.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/sleep.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/syscall.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/common.rb +29 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/infloop.rb +24 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/memcpy.rb +17 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/mov.rb +17 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/pushstr.rb +17 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/pushstr_array.rb +86 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/setregs.rb +84 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/cat.rb +54 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/execve.rb +72 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/exit.rb +34 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/linux.rb +16 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/ls.rb +67 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/open.rb +47 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/sh.rb +53 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/sleep.rb +52 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/syscall.rb +52 -0
- data/lib/pwnlib/shellcraft/registers.rb +148 -0
- data/lib/pwnlib/shellcraft/shellcraft.rb +73 -0
- data/lib/pwnlib/timer.rb +67 -0
- data/lib/pwnlib/tubes/buffer.rb +99 -0
- data/lib/pwnlib/tubes/process.rb +155 -0
- data/lib/pwnlib/tubes/serialtube.rb +114 -0
- data/lib/pwnlib/tubes/sock.rb +101 -0
- data/lib/pwnlib/tubes/tube.rb +442 -0
- data/lib/pwnlib/ui.rb +21 -0
- data/lib/pwnlib/util/cyclic.rb +97 -94
- data/lib/pwnlib/util/fiddling.rb +288 -220
- data/lib/pwnlib/util/getdents.rb +85 -0
- data/lib/pwnlib/util/hexdump.rb +116 -112
- data/lib/pwnlib/util/lists.rb +58 -0
- data/lib/pwnlib/util/packing.rb +223 -228
- data/lib/pwnlib/util/ruby.rb +19 -0
- data/lib/pwnlib/version.rb +3 -1
- data/test/abi_test.rb +22 -0
- data/test/asm_test.rb +177 -0
- data/test/constants/constant_test.rb +2 -0
- data/test/constants/constants_test.rb +5 -2
- data/test/context_test.rb +14 -3
- data/test/data/assembly/aarch64.s +19 -0
- data/test/data/assembly/amd64.s +21 -0
- data/test/data/assembly/arm.s +9 -0
- data/test/data/assembly/i386.s +21 -0
- data/test/data/assembly/mips.s +16 -0
- data/test/data/assembly/mips64.s +6 -0
- data/test/data/assembly/powerpc.s +18 -0
- data/test/data/assembly/powerpc64.s +36 -0
- data/test/data/assembly/sparc.s +33 -0
- data/test/data/assembly/sparc64.s +5 -0
- data/test/data/assembly/thumb.s +37 -0
- data/test/data/echo.rb +16 -0
- data/test/data/elfs/Makefile +24 -0
- data/test/data/elfs/amd64.frelro.elf +0 -0
- data/test/data/elfs/amd64.frelro.pie.elf +0 -0
- data/test/data/elfs/amd64.nrelro.elf +0 -0
- data/test/data/elfs/amd64.prelro.elf +0 -0
- data/test/data/elfs/amd64.static.elf +0 -0
- data/test/data/elfs/i386.frelro.pie.elf +0 -0
- data/test/data/elfs/i386.prelro.elf +0 -0
- data/test/data/elfs/source.cpp +19 -0
- data/test/data/flag +1 -0
- data/test/data/lib32/ld.so.2 +0 -0
- data/test/data/lib32/libc.so.6 +0 -0
- data/test/data/lib64/ld.so.2 +0 -0
- data/test/data/lib64/libc.so.6 +0 -0
- data/test/dynelf_test.rb +62 -25
- data/test/elf/elf_test.rb +147 -0
- data/test/ext_test.rb +4 -2
- data/test/files/use_pwn.rb +3 -6
- data/test/files/use_pwnlib.rb +2 -1
- data/test/full_file_test.rb +6 -0
- data/test/logger_test.rb +120 -0
- data/test/memleak_test.rb +5 -33
- data/test/reg_sort_test.rb +4 -1
- data/test/runner_test.rb +32 -0
- data/test/shellcraft/infloop_test.rb +27 -0
- data/test/shellcraft/linux/cat_test.rb +87 -0
- data/test/shellcraft/linux/ls_test.rb +109 -0
- data/test/shellcraft/linux/sh_test.rb +120 -0
- data/test/shellcraft/linux/sleep_test.rb +68 -0
- data/test/shellcraft/linux/syscalls/execve_test.rb +137 -0
- data/test/shellcraft/linux/syscalls/exit_test.rb +57 -0
- data/test/shellcraft/linux/syscalls/open_test.rb +87 -0
- data/test/shellcraft/linux/syscalls/syscall_test.rb +84 -0
- data/test/shellcraft/memcpy_test.rb +50 -0
- data/test/shellcraft/mov_test.rb +99 -0
- data/test/shellcraft/nop_test.rb +27 -0
- data/test/shellcraft/popad_test.rb +30 -0
- data/test/shellcraft/pushstr_array_test.rb +92 -0
- data/test/shellcraft/pushstr_test.rb +109 -0
- data/test/shellcraft/registers_test.rb +33 -0
- data/test/shellcraft/ret_test.rb +31 -0
- data/test/shellcraft/setregs_test.rb +63 -0
- data/test/shellcraft/shellcraft_test.rb +30 -0
- data/test/test_helper.rb +61 -2
- data/test/timer_test.rb +42 -0
- data/test/tubes/buffer_test.rb +46 -0
- data/test/tubes/process_test.rb +105 -0
- data/test/tubes/serialtube_test.rb +162 -0
- data/test/tubes/sock_test.rb +68 -0
- data/test/tubes/tube_test.rb +320 -0
- data/test/ui_test.rb +18 -0
- data/test/util/cyclic_test.rb +3 -1
- data/test/util/fiddling_test.rb +12 -3
- data/test/util/getdents_test.rb +33 -0
- data/test/util/hexdump_test.rb +9 -10
- data/test/util/lists_test.rb +22 -0
- data/test/util/packing_test.rb +5 -3
- metadata +357 -37
@@ -0,0 +1,36 @@
|
|
1
|
+
# These tests are fetched from Capstone's test_ppc.c
|
2
|
+
|
3
|
+
# context: endian: big
|
4
|
+
# !skip asm
|
5
|
+
# PPC-64
|
6
|
+
1000: 43 20 0c 07 bdnzla+ 0xc04
|
7
|
+
1004: 41 56 7f 17 bdztla 4*cr5+eq, 0x7f14
|
8
|
+
# Inconsistent output between capstone3 and later versions, skip
|
9
|
+
; 1008: 80 20 00 00 lwz r1, 0(0)
|
10
|
+
; 100c: 80 3f 00 00 lwz r1, 0(r31)
|
11
|
+
1008: 10 43 23 0e vpkpx v2, v3, v4
|
12
|
+
100c: d0 44 00 80 stfs f2, 0x80(r4)
|
13
|
+
1010: 4c 43 22 02 crand 2, 3, 4
|
14
|
+
1014: 2d 03 00 80 cmpwi cr2, r3, 0x80
|
15
|
+
1018: 7c 43 20 14 addc r2, r3, r4
|
16
|
+
101c: 7c 43 20 93 mulhd. r2, r3, r4
|
17
|
+
1020: 4f 20 00 21 bdnzlrl+
|
18
|
+
1024: 4c c8 00 21 bgelrl- cr2
|
19
|
+
1028: 40 82 00 14 bne 0x103c
|
20
|
+
|
21
|
+
# context: endian: big
|
22
|
+
# !skip disasm
|
23
|
+
# PPC-64
|
24
|
+
1000: 43 20 0c 07 bdnzla+ 0xc04
|
25
|
+
1004: 41 56 7f 17 bdztla 4*cr5+eq, 0x7f14
|
26
|
+
1008: 80 20 00 00 lwz 1, 0(0)
|
27
|
+
1010: 80 3f 00 00 lwz 1, 0(31)
|
28
|
+
1014: 10 43 23 0e vpkpx 2, 3, 4
|
29
|
+
1018: d0 44 00 80 stfs 2, 0x80(4)
|
30
|
+
101c: 4c 43 22 02 crand 2, 3, 4
|
31
|
+
1020: 2d 03 00 80 cmpwi cr2, 3, 0x80
|
32
|
+
1024: 7c 43 20 14 addc 2, 3, 4
|
33
|
+
1028: 7c 43 20 93 mulhd. 2, 3, 4
|
34
|
+
102c: 4f 20 00 21 bdnzlrl+
|
35
|
+
1030: 4c c8 00 21 bgelrl- cr2
|
36
|
+
1034: 40 82 00 14 bne 0x1044
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# These tests are fetched from Capstone's test_sparc.c
|
2
|
+
|
3
|
+
# !skip asm # because of keystone-engine/keystone#405
|
4
|
+
1000: 80 a0 40 02 cmp %g1, %g2
|
5
|
+
1004: 85 c2 60 08 jmpl %o1+8, %g2
|
6
|
+
1008: 85 e8 20 01 restore %g0, 1, %g2
|
7
|
+
100c: 81 e8 00 00 restore
|
8
|
+
1010: 90 10 20 01 mov 1, %o0
|
9
|
+
1014: d5 f6 10 16 casx [%i0], %l6, %o2
|
10
|
+
1018: 21 00 00 0a sethi 0xa, %l0
|
11
|
+
101c: 86 00 40 02 add %g1, %g2, %g3
|
12
|
+
1020: 01 00 00 00 nop
|
13
|
+
1024: 12 bf ff ff bne 0x1020
|
14
|
+
1028: 10 bf ff ff ba 0x1024
|
15
|
+
102c: a0 02 00 09 add %o0, %o1, %l0
|
16
|
+
1030: 0d bf ff ff fbg 0x102c
|
17
|
+
1034: d4 20 40 00 st %o2, [%g1]
|
18
|
+
1038: d4 4e 00 16 ldsb [%i0+%l6], %o2
|
19
|
+
# The output between objdump/llvm/capstone is inconsistent
|
20
|
+
; 103c: 2a c2 80 03 brnz,a,pn %o2, 0x1048
|
21
|
+
|
22
|
+
# Copied from above, ignored branch instructions
|
23
|
+
1000: 80 a0 40 02 cmp %g1, %g2
|
24
|
+
1004: 85 e8 20 01 restore %g0, 1, %g2
|
25
|
+
1008: 81 e8 00 00 restore
|
26
|
+
100c: 90 10 20 01 mov 1, %o0
|
27
|
+
1010: d5 f6 10 16 casx [%i0], %l6, %o2
|
28
|
+
1014: 21 00 00 0a sethi 0xa, %l0
|
29
|
+
1018: 86 00 40 02 add %g1, %g2, %g3
|
30
|
+
101c: 01 00 00 00 nop
|
31
|
+
1020: a0 02 00 09 add %o0, %o1, %l0
|
32
|
+
1024: d4 20 40 00 st %o2, [%g1]
|
33
|
+
1028: d4 4e 00 16 ldsb [%i0+%l6], %o2
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# These tests are fetched from Capstone's test_arm.c
|
2
|
+
# Thumb
|
3
|
+
# PC-relative instructions are buggy in Capstone3, two lines are commented.
|
4
|
+
80001000: 60 f9 1f 04 vld3.8 {d16, d17, d18}, [r0:0x40]
|
5
|
+
80001004: e0 f9 4f 07 vld4.16 {d16[1], d17[1], d18[1], d19[1]}, [r0]
|
6
|
+
80001008: 70 47 bx lr
|
7
|
+
; 8000100a: 00 f0 10 e8 blx #0x8000102c
|
8
|
+
8000100a: eb 46 mov fp, sp
|
9
|
+
8000100c: 83 b0 sub sp, #0xc
|
10
|
+
8000100e: c9 68 ldr r1, [r1, #0xc]
|
11
|
+
; 80001010: 1f b1 cbz r7, #0x8000101e
|
12
|
+
80001010: 30 bf wfi
|
13
|
+
80001012: af f3 20 84 cpsie.w f
|
14
|
+
80001016: 52 f8 23 f0 ldr.w pc, [r2, r3, lsl #2]
|
15
|
+
|
16
|
+
# Thumb-mixed
|
17
|
+
80001000: d1 e8 00 f0 tbb [r1, r0]
|
18
|
+
80001004: f0 24 movs r4, #0xf0
|
19
|
+
80001006: 04 07 lsls r4, r0, #0x1c
|
20
|
+
80001008: 1f 3c subs r4, #0x1f
|
21
|
+
8000100a: f2 c0 stm r0!, {r1, r4, r5, r6, r7}
|
22
|
+
8000100c: 00 00 movs r0, r0
|
23
|
+
8000100e: 4f f0 00 01 mov.w r1, #0
|
24
|
+
80001012: 46 6c ldr r6, [r0, #0x44]
|
25
|
+
|
26
|
+
# Thumb-2 & register named with numbers
|
27
|
+
# An `iteet` instruction is removed to make the `it` instruction valid
|
28
|
+
80001000: 4f f0 00 01 mov.w r1, #0
|
29
|
+
80001004: bd e8 00 88 pop.w {fp, pc}
|
30
|
+
80001008: d1 e8 00 f0 tbb [r1, r0]
|
31
|
+
8000100c: 18 bf it ne
|
32
|
+
; 8000100e: ad bf iteet ge
|
33
|
+
8000100e: f3 ff 0b 0c vdupne.8 d16, d11[1]
|
34
|
+
80001012: 86 f3 00 89 msr cpsr_fc, r6
|
35
|
+
80001016: 80 f3 00 8c msr apsr_nzcvqg, r0
|
36
|
+
8000101a: 4f fa 99 f6 sxtb.w r6, sb, ror #8
|
37
|
+
8000101e: d0 ff a2 01 vaddw.u16 q8, q8, d18
|
data/test/data/echo.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
server = TCPServer.open('127.0.0.1', 0)
|
7
|
+
|
8
|
+
$stdout.puts "Start with port #{server.addr[1]}"
|
9
|
+
$stdout.flush
|
10
|
+
|
11
|
+
client = server.accept
|
12
|
+
s = client.gets
|
13
|
+
client.puts(s)
|
14
|
+
client.close
|
15
|
+
|
16
|
+
$stdout.puts 'Bye!'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
source=source.cpp
|
2
|
+
FLAGS=
|
3
|
+
PIE_FLAGS=-pie
|
4
|
+
NOPIE_FLAGS=-no-pie
|
5
|
+
FULL_RELRO_FLAGS=-Wl,-z,relro,-z,now
|
6
|
+
PARTIAL_RELRO_FLAGS=-Wl,-z,relro
|
7
|
+
NO_RELRO_FLAGS=-Wl,-z,norelro
|
8
|
+
STATIC_FLAGS=-static
|
9
|
+
TARGETS=amd64 i386
|
10
|
+
.PHONY: clean
|
11
|
+
all: ${TARGETS}
|
12
|
+
|
13
|
+
amd64: ${source}
|
14
|
+
g++ -m64 ${source} -o amd64.frelro.elf ${FLAGS} ${FULL_RELRO_FLAGS} ${NOPIE_FLAGS}
|
15
|
+
g++ -m64 ${source} -o amd64.frelro.pie.elf ${FLAGS} ${FULL_RELRO_FLAGS} ${PIE_FLAGS}
|
16
|
+
g++ -m64 ${source} -o amd64.prelro.elf ${FLAGS} ${PARTIAL_RELRO_FLAGS} ${NOPIE_FLAGS}
|
17
|
+
g++ -m64 ${source} -o amd64.nrelro.elf ${FLAGS} ${NO_RELRO_FLAGS} ${NOPIE_FLAGS}
|
18
|
+
g++ -m64 ${source} -o amd64.static.elf ${FLAGS} ${STATIC_FLAGS} ${NOPIE_FLAGS}
|
19
|
+
i386: ${source}
|
20
|
+
g++ -m32 ${source} -o i386.prelro.elf ${FLAGS} ${PARTIAL_RELRO_FLAGS} ${NOPIE_FLAGS}
|
21
|
+
g++ -m32 ${source} -o i386.frelro.pie.elf ${FLAGS} ${FULL_RELRO_FLAGS} ${PIE_FLAGS}
|
22
|
+
|
23
|
+
clean:
|
24
|
+
rm -f *.elf
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
char s[101];
|
4
|
+
void func() {
|
5
|
+
static int test = 0;
|
6
|
+
test++;
|
7
|
+
puts("In func:");
|
8
|
+
printf("test = %d\n", test);
|
9
|
+
}
|
10
|
+
int main() {
|
11
|
+
fgets(s, 100, stdin);
|
12
|
+
printf("%s", s);
|
13
|
+
int n;
|
14
|
+
scanf("%d", &n);
|
15
|
+
while(n--) {
|
16
|
+
func();
|
17
|
+
}
|
18
|
+
return 0;
|
19
|
+
}
|
data/test/data/flag
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
flag{pwntools_ruby}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/dynelf_test.rb
CHANGED
@@ -1,47 +1,84 @@
|
|
1
1
|
# encoding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'open3'
|
4
5
|
|
5
6
|
require 'tty-platform'
|
6
7
|
|
7
8
|
require 'test_helper'
|
9
|
+
|
10
|
+
require 'pwnlib/context'
|
8
11
|
require 'pwnlib/dynelf'
|
12
|
+
require 'pwnlib/elf/elf'
|
9
13
|
|
10
14
|
class DynELFTest < MiniTest::Test
|
11
|
-
|
12
|
-
|
15
|
+
include ::Pwnlib
|
16
|
+
include ::Pwnlib::Context
|
17
|
+
include ::Pwnlib::ELF
|
18
|
+
|
19
|
+
def setup
|
20
|
+
linux_only
|
21
|
+
end
|
22
|
+
|
23
|
+
# popen victim with specific libc.so.6
|
24
|
+
def popen_victim(b)
|
25
|
+
lib_path = File.expand_path("data/lib#{b}/", __dir__)
|
26
|
+
libc_path = File.expand_path('libc.so.6', lib_path)
|
27
|
+
ld_path = File.expand_path('ld.so.2', lib_path)
|
28
|
+
victim_path = File.expand_path("data/victim#{b}", __dir__)
|
29
|
+
|
30
|
+
Open3.popen2("#{ld_path} --library-path #{lib_path} #{victim_path}") do |i, o, t|
|
31
|
+
main_ra = Integer(o.readline)
|
32
|
+
mem = open("/proc/#{t.pid}/mem", 'rb')
|
33
|
+
d = DynELF.new(main_ra) do |addr|
|
34
|
+
mem.seek(addr)
|
35
|
+
mem.getc
|
36
|
+
end
|
37
|
+
|
38
|
+
yield d, { libc: libc_path, main_ra: main_ra, pid: t.pid }
|
39
|
+
|
40
|
+
mem.close
|
41
|
+
i.write('bye')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_find_base
|
13
46
|
[32, 64].each do |b|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
IO.readlines("/proc/#{t.pid}/maps").map(&:split).each do |s|
|
47
|
+
popen_victim(b) do |d, options|
|
48
|
+
main_ra = options[:main_ra]
|
49
|
+
realbase = nil
|
50
|
+
IO.readlines("/proc/#{options[:pid]}/maps").map(&:split).each do |s|
|
19
51
|
st, ed = s[0].split('-').map { |x| x.to_i(16) }
|
20
52
|
next unless main_ra.between?(st, ed)
|
21
|
-
|
53
|
+
|
54
|
+
realbase = st
|
22
55
|
break
|
23
56
|
end
|
24
|
-
refute_nil(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
h = Hash.new { |hsh, key| hsh[key] = [] }
|
30
|
-
symbols = `objdump -T #{libc_path}`.lines.map(&:split).select { |a| a[2] == 'DF' }
|
31
|
-
symbols.map { |a| h[a[-1]] << a[0].to_i(16) }
|
32
|
-
|
33
|
-
mem = open("/proc/#{t.pid}/mem", 'rb')
|
34
|
-
d = ::Pwnlib::DynELF.new(main_ra) do |addr|
|
35
|
-
mem.seek(addr)
|
36
|
-
mem.getc
|
37
|
-
end
|
57
|
+
refute_nil(realbase)
|
58
|
+
assert_equal(realbase, d.libbase)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
38
62
|
|
63
|
+
def test_lookup
|
64
|
+
[32, 64].each do |b|
|
65
|
+
popen_victim(b) do |d, options|
|
39
66
|
assert_nil(d.lookup('pipi_hao_wei!'))
|
40
|
-
|
41
|
-
|
67
|
+
elf = ELF.new(options[:libc], checksec: false)
|
68
|
+
%i(system open read write execve printf puts sprintf mmap mprotect).each do |sym|
|
69
|
+
assert_equal(d.libbase + elf.symbols[sym], d.lookup(sym))
|
42
70
|
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
43
74
|
|
44
|
-
|
75
|
+
def test_build_id
|
76
|
+
[
|
77
|
+
[32, 'ac333186c6b532511a68d16aca4c61422eb772da', 'i386'],
|
78
|
+
[64, '088a6e00a1814622219f346b41e775b8dd46c518', 'amd64']
|
79
|
+
].each do |b, answer, arch|
|
80
|
+
context.local(arch: arch) do
|
81
|
+
popen_victim(b) { |d| assert_equal(answer, d.build_id) }
|
45
82
|
end
|
46
83
|
end
|
47
84
|
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'test_helper'
|
5
|
+
|
6
|
+
require 'pwnlib/context'
|
7
|
+
require 'pwnlib/elf/elf'
|
8
|
+
require 'pwnlib/logger'
|
9
|
+
|
10
|
+
class ELFTest < MiniTest::Test
|
11
|
+
include ::Pwnlib::Context
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@path_of = ->(file) { File.join(__dir__, '..', 'data', 'elfs', file) }
|
15
|
+
@elf = to_elf_silent('i386.prelro.elf')
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_elf_silent(filename)
|
19
|
+
log_null { ::Pwnlib::ELF::ELF.new(@path_of.call(filename), checksec: false) }
|
20
|
+
end
|
21
|
+
|
22
|
+
# check stdout when loaded
|
23
|
+
def test_load
|
24
|
+
file = @path_of.call('amd64.prelro.elf')
|
25
|
+
assert_output(<<-EOS) { log_stdout { ::Pwnlib::ELF::ELF.new(file) } }
|
26
|
+
[INFO] #{File.realpath(file).inspect}
|
27
|
+
RELRO: Partial RELRO
|
28
|
+
Stack: Canary found
|
29
|
+
NX: NX enabled
|
30
|
+
PIE: No PIE (0x400000)
|
31
|
+
EOS
|
32
|
+
|
33
|
+
file = @path_of.call('amd64.frelro.elf')
|
34
|
+
assert_output(<<-EOS) { log_stdout { ::Pwnlib::ELF::ELF.new(file) } }
|
35
|
+
[WARN] No REL.PLT section found, PLT not loaded
|
36
|
+
[INFO] #{File.realpath(file).inspect}
|
37
|
+
RELRO: Full RELRO
|
38
|
+
Stack: Canary found
|
39
|
+
NX: NX enabled
|
40
|
+
PIE: No PIE (0x400000)
|
41
|
+
EOS
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_checksec
|
45
|
+
assert_equal(<<-EOS.strip, @elf.checksec)
|
46
|
+
RELRO: Partial RELRO
|
47
|
+
Stack: Canary found
|
48
|
+
NX: NX enabled
|
49
|
+
PIE: No PIE (0x8048000)
|
50
|
+
EOS
|
51
|
+
|
52
|
+
nrelro_elf = to_elf_silent('amd64.nrelro.elf')
|
53
|
+
assert_equal(<<-EOS.strip, nrelro_elf.checksec)
|
54
|
+
RELRO: No RELRO
|
55
|
+
Stack: Canary found
|
56
|
+
NX: NX enabled
|
57
|
+
PIE: No PIE (0x400000)
|
58
|
+
EOS
|
59
|
+
|
60
|
+
frelro_elf = to_elf_silent('amd64.frelro.elf')
|
61
|
+
assert_equal(<<-EOS.strip, frelro_elf.checksec)
|
62
|
+
RELRO: Full RELRO
|
63
|
+
Stack: Canary found
|
64
|
+
NX: NX enabled
|
65
|
+
PIE: No PIE (0x400000)
|
66
|
+
EOS
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_inspect
|
70
|
+
assert_match(/#<Pwnlib::ELF::ELF:0x[0-9a-f]+>/, @elf.inspect)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_got
|
74
|
+
assert_same(8, @elf.got.to_h.size)
|
75
|
+
assert_same(0x8049ff8, @elf.got['__gmon_start__'])
|
76
|
+
assert_same(0x8049ff8, @elf.got[:__gmon_start__])
|
77
|
+
assert_same(0x804a000, @elf.symbols['_GLOBAL_OFFSET_TABLE_'])
|
78
|
+
assert_same(0x804856d, @elf.symbols['main'])
|
79
|
+
assert_same(@elf.symbols.main, @elf.symbols[:main])
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_plt
|
83
|
+
assert_same(6, @elf.plt.to_h.size)
|
84
|
+
assert_same(0x80483b0, @elf.plt.printf)
|
85
|
+
assert_same(0x80483f0, @elf.plt[:scanf])
|
86
|
+
|
87
|
+
elf = to_elf_silent('amd64.frelro.pie.elf')
|
88
|
+
assert_nil(elf.plt)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_address
|
92
|
+
old_address = @elf.address
|
93
|
+
assert_equal(0x8048000, @elf.address)
|
94
|
+
old_main = @elf.symbols.main
|
95
|
+
new_address = 0x12340000
|
96
|
+
@elf.address = new_address
|
97
|
+
assert_equal(old_main - old_address + new_address, @elf.symbols.main)
|
98
|
+
|
99
|
+
elf = to_elf_silent('i386.frelro.pie.elf')
|
100
|
+
assert_equal(0, elf.address)
|
101
|
+
assert_same(0x6c2, elf.symbols.main)
|
102
|
+
elf.address = 0xdeadbeef0000
|
103
|
+
# use 'equal' instead of 'same' because their +object_id+ are different on Windows.
|
104
|
+
assert_equal(0xdeadbeef06c2, elf.symbols.main)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_static
|
108
|
+
elf = to_elf_silent('amd64.static.elf')
|
109
|
+
assert_equal(<<-EOS.strip, elf.checksec)
|
110
|
+
RELRO: Partial RELRO
|
111
|
+
Stack: Canary found
|
112
|
+
NX: NX enabled
|
113
|
+
PIE: No PIE (0x400000)
|
114
|
+
EOS
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_search
|
118
|
+
elf = ::Pwnlib::ELF::ELF.new(File.join(__dir__, '..', 'data', 'lib32', 'libc.so.6'), checksec: false)
|
119
|
+
assert_equal([0x1, 0x15e613], elf.search('ELF').to_a)
|
120
|
+
assert_equal(0x15900b, elf.find('/bin/sh').next)
|
121
|
+
|
122
|
+
result = elf.find(/E.F/)
|
123
|
+
assert_equal(0x1, result.next)
|
124
|
+
assert_equal(0xc8efa, result.next)
|
125
|
+
assert_equal(0xc9118, result.next)
|
126
|
+
assert_equal(0x158284, result.next)
|
127
|
+
assert_equal(0x158285, result.next)
|
128
|
+
|
129
|
+
elf.address = 0x1234000
|
130
|
+
assert_equal([0x1234001, 0x1392613], elf.search('ELF').to_a)
|
131
|
+
assert_equal(0x138d00b, elf.find('/bin/sh').next)
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_one_gadgets
|
135
|
+
libc = ::Pwnlib::ELF::ELF.new(File.join(__dir__, '..', 'data', 'lib64', 'libc.so.6'), checksec: false)
|
136
|
+
# Well.. one_gadget(s) may change in the future, so we just check the return type
|
137
|
+
val = libc.one_gadgets.first
|
138
|
+
assert(val.is_a?(Integer))
|
139
|
+
assert_equal(libc.one_gadgets[0], val)
|
140
|
+
assert_equal(libc.one_gadgets[-1], libc.one_gadgets.last)
|
141
|
+
|
142
|
+
libc.address = 0xdeadf000
|
143
|
+
assert_equal(0xdeadf000 + val, libc.one_gadgets[0])
|
144
|
+
|
145
|
+
assert_output(/execve/) { log_stdout { context.local(log_level: :debug) { libc.one_gadgets[0] } } }
|
146
|
+
end
|
147
|
+
end
|