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,34 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pwnlib/shellcraft/generators/x86/linux/linux'
|
5
|
+
|
6
|
+
module Pwnlib
|
7
|
+
module Shellcraft
|
8
|
+
module Generators
|
9
|
+
module X86
|
10
|
+
module Linux
|
11
|
+
# Exit syscall.
|
12
|
+
#
|
13
|
+
# @param [Integer] status
|
14
|
+
# Status code.
|
15
|
+
#
|
16
|
+
# @return [String]
|
17
|
+
# Assembly for invoking exit syscall.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# puts shellcraft.exit(1)
|
21
|
+
# # /* call exit(1) */
|
22
|
+
# # push 1 /* (SYS_exit) */
|
23
|
+
# # pop eax
|
24
|
+
# # push 1
|
25
|
+
# # pop ebx
|
26
|
+
# # int 0x80
|
27
|
+
def exit(status = 0)
|
28
|
+
cat Linux.syscall('SYS_exit', status)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pwnlib/shellcraft/generators/helper'
|
4
|
+
|
5
|
+
module Pwnlib
|
6
|
+
module Shellcraft
|
7
|
+
module Generators
|
8
|
+
module X86
|
9
|
+
# For os-related methods.
|
10
|
+
module Linux
|
11
|
+
extend ::Pwnlib::Shellcraft::Generators::Helper
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pwnlib/shellcraft/generators/x86/common/pushstr'
|
5
|
+
require 'pwnlib/shellcraft/generators/x86/linux/linux'
|
6
|
+
require 'pwnlib/shellcraft/generators/x86/linux/syscall'
|
7
|
+
|
8
|
+
module Pwnlib
|
9
|
+
module Shellcraft
|
10
|
+
module Generators
|
11
|
+
module X86
|
12
|
+
module Linux
|
13
|
+
# List files.
|
14
|
+
#
|
15
|
+
# @param [String] dir
|
16
|
+
# The relative path to be listed.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# context.arch = 'amd64'
|
20
|
+
# puts shellcraft.ls
|
21
|
+
# # /* push ".\x00" */
|
22
|
+
# # push 0x2e
|
23
|
+
# # /* call open("rsp", 0, 0) */
|
24
|
+
# # push 2 /* (SYS_open) */
|
25
|
+
# # pop rax
|
26
|
+
# # mov rdi, rsp
|
27
|
+
# # xor esi, esi /* 0 */
|
28
|
+
# # cdq /* rdx=0 */
|
29
|
+
# # syscall
|
30
|
+
# # /* call getdents("rax", "rsp", 4096) */
|
31
|
+
# # mov rdi, rax
|
32
|
+
# # push 0x4e /* (SYS_getdents) */
|
33
|
+
# # pop rax
|
34
|
+
# # mov rsi, rsp
|
35
|
+
# # xor edx, edx
|
36
|
+
# # mov dh, 0x1000 >> 8
|
37
|
+
# # syscall
|
38
|
+
# # /* call write(1, "rsp", "rax") */
|
39
|
+
# # push 1
|
40
|
+
# # pop rdi
|
41
|
+
# # mov rsi, rsp
|
42
|
+
# # mov rdx, rax
|
43
|
+
# # push 1 /* (SYS_write) */
|
44
|
+
# # pop rax
|
45
|
+
# # syscall
|
46
|
+
# #=> nil
|
47
|
+
#
|
48
|
+
# @note
|
49
|
+
# This shellcode will output the binary data returned by syscall +getdents+.
|
50
|
+
# Use {Pwnlib::Util::Getdents.parse} to parse the output.
|
51
|
+
def ls(dir = '.')
|
52
|
+
abi = ::Pwnlib::ABI::ABI.syscall
|
53
|
+
cat Common.pushstr(dir)
|
54
|
+
cat Linux.syscall('SYS_open', abi.stack_pointer, 0, 0)
|
55
|
+
# In x86, return value register is same as sysnr register.
|
56
|
+
ret = abi.register_arguments.first
|
57
|
+
# XXX(david942j): Will fixed size 0x1000 be an issue?
|
58
|
+
cat Linux.syscall('SYS_getdents', ret, abi.stack_pointer, 0x1000) # getdents(fd, buf, sz)
|
59
|
+
|
60
|
+
# Just write all the shits out
|
61
|
+
cat Linux.syscall('SYS_write', 1, abi.stack_pointer, ret)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pwnlib/shellcraft/generators/x86/linux/linux'
|
5
|
+
|
6
|
+
module Pwnlib
|
7
|
+
module Shellcraft
|
8
|
+
module Generators
|
9
|
+
module X86
|
10
|
+
module Linux
|
11
|
+
# Push filename onto stack and perform open syscall.
|
12
|
+
#
|
13
|
+
# @param [String] filename
|
14
|
+
# The file to be opened.
|
15
|
+
# @param [String, Integer] flags
|
16
|
+
# Flags for opening a file.
|
17
|
+
# @param [Integer] mode
|
18
|
+
# If +filename+ doesn't exist and 'O_CREAT' is specified in +flags+,
|
19
|
+
# +mode+ will be used as the file permission for creating the file.
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
# Assembly for syscall open.
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# puts shellcraft.open('/etc/passwd', 'O_RDONLY')
|
26
|
+
# # /* push "/etc/passwd\x00" */
|
27
|
+
# # push 0x1010101
|
28
|
+
# # xor dword ptr [esp], 0x1657672 /* 0x1010101 ^ 0x647773 */
|
29
|
+
# # push 0x7361702f
|
30
|
+
# # push 0x6374652f
|
31
|
+
# # /* call open("esp", "O_RDONLY", 0) */
|
32
|
+
# # push 5 /* (SYS_open) */
|
33
|
+
# # pop eax
|
34
|
+
# # mov ebx, esp
|
35
|
+
# # xor ecx, ecx /* (O_RDONLY) */
|
36
|
+
# # cdq /* edx=0 */
|
37
|
+
# # int 0x80
|
38
|
+
def open(filename, flags = 'O_RDONLY', mode = 0)
|
39
|
+
abi = ::Pwnlib::ABI::ABI.syscall
|
40
|
+
cat Common.pushstr(filename)
|
41
|
+
cat Linux.syscall('SYS_open', abi.stack_pointer, flags, mode)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pwnlib/shellcraft/generators/x86/linux/execve'
|
5
|
+
require 'pwnlib/shellcraft/generators/x86/linux/linux'
|
6
|
+
|
7
|
+
module Pwnlib
|
8
|
+
module Shellcraft
|
9
|
+
module Generators
|
10
|
+
module X86
|
11
|
+
module Linux
|
12
|
+
# Get shell!
|
13
|
+
#
|
14
|
+
# @param [Boolean, Array<String>] argv
|
15
|
+
# Arguments of +argv+ when calling +execve+.
|
16
|
+
# If +true+ is given, use +['sh']+.
|
17
|
+
# If +Array<String>+ is given, use it as arguments array.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# context.arch = 'i386'
|
21
|
+
# puts shellcraft.sh
|
22
|
+
# # /* push "/bin///sh\x00" */
|
23
|
+
# # push 0x68
|
24
|
+
# # push 0x732f2f2f
|
25
|
+
# # push 0x6e69622f
|
26
|
+
# #
|
27
|
+
# # /* call execve("esp", 0, 0) */
|
28
|
+
# # push 0xb /* (SYS_execve) */
|
29
|
+
# # pop eax
|
30
|
+
# # mov ebx, esp
|
31
|
+
# # xor ecx, ecx /* 0 */
|
32
|
+
# # cdq /* edx=0 */
|
33
|
+
# # int 0x80
|
34
|
+
# #=> nil
|
35
|
+
#
|
36
|
+
# @note Null pointer is always used as +envp+.
|
37
|
+
#
|
38
|
+
# @diff
|
39
|
+
# By default, this method calls +execve('/bin///sh', 0, 0)+, which is different from pwntools-python:
|
40
|
+
# +execve('/bin///sh', ['sh'], 0)+.
|
41
|
+
def sh(argv: false)
|
42
|
+
argv = case argv
|
43
|
+
when true then ['sh']
|
44
|
+
when false then 0
|
45
|
+
else argv
|
46
|
+
end
|
47
|
+
cat Linux.execve('/bin///sh', argv, 0)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pwnlib/shellcraft/generators/x86/common/pushstr'
|
5
|
+
require 'pwnlib/shellcraft/generators/x86/linux/linux'
|
6
|
+
require 'pwnlib/shellcraft/generators/x86/linux/syscall'
|
7
|
+
require 'pwnlib/util/packing'
|
8
|
+
|
9
|
+
module Pwnlib
|
10
|
+
module Shellcraft
|
11
|
+
module Generators
|
12
|
+
module X86
|
13
|
+
module Linux
|
14
|
+
# Sleep for a specified number of seconds.
|
15
|
+
#
|
16
|
+
# @param [Float] seconds
|
17
|
+
# The seconds to sleep.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# context.arch = :amd64
|
21
|
+
# puts shellcraft.sleep(1)
|
22
|
+
# # /* push "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" */
|
23
|
+
# # push 1
|
24
|
+
# # dec byte ptr [rsp]
|
25
|
+
# # push 1
|
26
|
+
# # /* call nanosleep("rsp", 0) */
|
27
|
+
# # push 0x23 /* (SYS_nanosleep) */
|
28
|
+
# # pop rax
|
29
|
+
# # mov rdi, rsp
|
30
|
+
# # xor esi, esi /* 0 */
|
31
|
+
# # syscall
|
32
|
+
# # add rsp, 16 /* recover rsp */
|
33
|
+
# #=> nil
|
34
|
+
#
|
35
|
+
# @note
|
36
|
+
# Syscall +nanosleep+ accepts a data pointer as argument, the stack will be used for putting the data
|
37
|
+
# needed. The generated assembly will use sizeof(struct timespec) = 16 bytes for putting data.
|
38
|
+
def sleep(seconds)
|
39
|
+
# pushes the data onto stack
|
40
|
+
tv_sec = seconds.to_i
|
41
|
+
tv_nsec = ((seconds - tv_sec) * 1e9).to_i
|
42
|
+
data = ::Pwnlib::Util::Packing.p64(tv_sec) + ::Pwnlib::Util::Packing.p64(tv_nsec)
|
43
|
+
cat Common.pushstr(data, append_null: false)
|
44
|
+
sp = ::Pwnlib::ABI::ABI.default.stack_pointer
|
45
|
+
cat Linux.syscall('SYS_nanosleep', sp, 0)
|
46
|
+
cat "add #{sp}, #{data.size} /* recover #{sp} */"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pwnlib/shellcraft/generators/x86/common/setregs'
|
5
|
+
require 'pwnlib/shellcraft/generators/x86/linux/linux'
|
6
|
+
require 'pwnlib/util/ruby'
|
7
|
+
|
8
|
+
module Pwnlib
|
9
|
+
module Shellcraft
|
10
|
+
module Generators
|
11
|
+
module X86
|
12
|
+
module Linux
|
13
|
+
# Assembly of +syscall+.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# context.arch = 'i386'
|
17
|
+
# puts shellcraft.syscall('SYS_open', 'esp', 0, 0)
|
18
|
+
# # /* call open("esp", 0, 0) */
|
19
|
+
# # push 5 /* (SYS_open) */
|
20
|
+
# # pop eax
|
21
|
+
# # mov ebx, esp
|
22
|
+
# # xor ecx, ecx /* 0 */
|
23
|
+
# # cdq /* edx=0 */
|
24
|
+
# # int 0x80
|
25
|
+
# #=> nil
|
26
|
+
def syscall(*arguments)
|
27
|
+
abi = ::Pwnlib::ABI::ABI.syscall
|
28
|
+
registers = abi.register_arguments
|
29
|
+
reg_ctx = registers.zip(arguments).to_h
|
30
|
+
syscall = arguments.first
|
31
|
+
if syscall.to_s.start_with?('SYS_')
|
32
|
+
fmt = "#{syscall.to_s[4..-1]}(%s)"
|
33
|
+
args = []
|
34
|
+
else
|
35
|
+
fmt = 'syscall(%s)'
|
36
|
+
args = [syscall ? syscall.inspect : '?']
|
37
|
+
end
|
38
|
+
# arg0 to arg5
|
39
|
+
1.upto(6) do |i|
|
40
|
+
args.push(arguments[i] ? arguments[i].inspect : '?')
|
41
|
+
end
|
42
|
+
args.pop while args.last == '?'
|
43
|
+
|
44
|
+
cat "/* call #{format(fmt, args.join(', '))} */"
|
45
|
+
cat Common.setregs(reg_ctx) if arguments.any? { |v| !v.nil? }
|
46
|
+
cat abi.syscall_str
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pwnlib/context'
|
4
|
+
|
5
|
+
module Pwnlib
|
6
|
+
module Shellcraft
|
7
|
+
# Define register names and methods for shellcode generators.
|
8
|
+
module Registers
|
9
|
+
X86_BASEREGS = %w(ax cx dx bx sp bp si di ip).freeze
|
10
|
+
|
11
|
+
I386 = (X86_BASEREGS.map { |r| "e#{r}" } +
|
12
|
+
X86_BASEREGS +
|
13
|
+
%w(eflags cs ss ds es fs gs)).freeze
|
14
|
+
|
15
|
+
AMD64 = (X86_BASEREGS.map { |r| "r#{r}" } +
|
16
|
+
(8..15).map { |r| "r#{r}" } +
|
17
|
+
(8..15).map { |r| "r#{r}d" } +
|
18
|
+
I386).freeze
|
19
|
+
|
20
|
+
# x86 registers in decreasing size
|
21
|
+
X86_ORDERED = ([
|
22
|
+
%w(rax eax ax al),
|
23
|
+
%w(rbx ebx bx bl),
|
24
|
+
%w(rcx ecx cx cl),
|
25
|
+
%w(rdx edx dx dl),
|
26
|
+
%w(rdi edi di),
|
27
|
+
%w(rsi esi si),
|
28
|
+
%w(rbp ebp bp),
|
29
|
+
%w(rsp esp sp)
|
30
|
+
] + (8..15).map { |r| ['', 'd', 'w', 'b'].map { |t| "r#{r}#{t}" } }).freeze
|
31
|
+
|
32
|
+
# class Register, currently only supports i386 and amd64.
|
33
|
+
class Register
|
34
|
+
# @return [String]
|
35
|
+
# Register's name.
|
36
|
+
attr_reader :name
|
37
|
+
attr_reader :bigger, :smaller, :ff00, :is64bit, :native64, :native32, :xor, :size, :sizes
|
38
|
+
|
39
|
+
# Instantiate a {Register} object.
|
40
|
+
#
|
41
|
+
# Create a register by its name and size (in bits) for fetching other information. For example, for register
|
42
|
+
# 'ax', +#bigger+ contains 'rax' and 'eax'.
|
43
|
+
#
|
44
|
+
# Normally you don't need to create any {Register} object, use {.get_register} to get register by name.
|
45
|
+
#
|
46
|
+
# @param [String] name
|
47
|
+
# Register's name.
|
48
|
+
# @param [Integer] size
|
49
|
+
# Register size in bits.
|
50
|
+
#
|
51
|
+
# @example
|
52
|
+
# Register.new('rax', 64)
|
53
|
+
# Register.new('bx', 16)
|
54
|
+
def initialize(name, size)
|
55
|
+
@name = name
|
56
|
+
@size = size
|
57
|
+
X86_ORDERED.each do |row|
|
58
|
+
next unless row.include?(name)
|
59
|
+
|
60
|
+
@bigger = row[0, row.index(name)]
|
61
|
+
@smaller = row[(row.index(name) + 1)..-1]
|
62
|
+
@native64 = row[0]
|
63
|
+
@native32 = row[1]
|
64
|
+
@sizes = row.each_with_object({}).with_index { |(r, h), i| h[64 >> i] = r }
|
65
|
+
@xor = @sizes[[size, 32].min]
|
66
|
+
break
|
67
|
+
end
|
68
|
+
@ff00 = "#{name[1]}h" if @size >= 32 && @name.end_with?('x')
|
69
|
+
@is64bit = true if @name.start_with?('r')
|
70
|
+
end
|
71
|
+
|
72
|
+
def bits
|
73
|
+
size
|
74
|
+
end
|
75
|
+
|
76
|
+
def bytes
|
77
|
+
bits / 8
|
78
|
+
end
|
79
|
+
|
80
|
+
def fits(value)
|
81
|
+
size >= Registers.bits_required(value)
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_s
|
85
|
+
name
|
86
|
+
end
|
87
|
+
|
88
|
+
def inspect
|
89
|
+
format('Register(%s)', name)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
module_function
|
94
|
+
|
95
|
+
def registers
|
96
|
+
{
|
97
|
+
[32, 'i386', 'linux'] => ::Pwnlib::Shellcraft::Registers::I386,
|
98
|
+
[64, 'amd64', 'linux'] => ::Pwnlib::Shellcraft::Registers::AMD64
|
99
|
+
}[[context.bits, context.arch, context.os]]
|
100
|
+
end
|
101
|
+
|
102
|
+
INTEL = (X86_ORDERED.each_with_object({}) do |row, obj|
|
103
|
+
row.each_with_index do |reg, i|
|
104
|
+
obj[reg] = Register.new(reg, 64 >> i)
|
105
|
+
end
|
106
|
+
end).freeze
|
107
|
+
|
108
|
+
# Get a {Register} object by name.
|
109
|
+
#
|
110
|
+
# @param [String, Symbol, Register] name
|
111
|
+
# The name of register.
|
112
|
+
# If +name+ is already a {Register} object, +name+ itself will be returned.
|
113
|
+
#
|
114
|
+
# @return [Register?]
|
115
|
+
# Get the register with name +name+.
|
116
|
+
#
|
117
|
+
# @example
|
118
|
+
# Registers.get_register('eax')
|
119
|
+
# #=> Register(eax)
|
120
|
+
# Registers.get_register(:ebx)
|
121
|
+
# #=> Register(ebx)
|
122
|
+
# Registers.get_register('xdd')
|
123
|
+
# #=> nil
|
124
|
+
def get_register(name)
|
125
|
+
return name if name.instance_of?(Register)
|
126
|
+
return INTEL[name.to_s] if name.instance_of?(String) || name.instance_of?(Symbol)
|
127
|
+
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
|
131
|
+
def register?(obj)
|
132
|
+
!get_register(obj).nil?
|
133
|
+
end
|
134
|
+
|
135
|
+
def bits_required(value)
|
136
|
+
bits = 0
|
137
|
+
value = value.abs
|
138
|
+
while value.positive?
|
139
|
+
bits += 8
|
140
|
+
value >>= 8
|
141
|
+
end
|
142
|
+
bits
|
143
|
+
end
|
144
|
+
|
145
|
+
include ::Pwnlib::Context
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|