pwntools 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +88 -11
  3. data/Rakefile +5 -1
  4. data/lib/pwn.rb +9 -7
  5. data/lib/pwnlib/abi.rb +60 -0
  6. data/lib/pwnlib/asm.rb +146 -0
  7. data/lib/pwnlib/constants/constant.rb +16 -2
  8. data/lib/pwnlib/constants/constants.rb +35 -19
  9. data/lib/pwnlib/constants/linux/amd64.rb +30 -1
  10. data/lib/pwnlib/context.rb +25 -17
  11. data/lib/pwnlib/dynelf.rb +117 -54
  12. data/lib/pwnlib/elf/elf.rb +267 -0
  13. data/lib/pwnlib/ext/helper.rb +4 -4
  14. data/lib/pwnlib/logger.rb +87 -0
  15. data/lib/pwnlib/memleak.rb +58 -29
  16. data/lib/pwnlib/pwn.rb +19 -8
  17. data/lib/pwnlib/reg_sort.rb +102 -108
  18. data/lib/pwnlib/shellcraft/generators/amd64/common/common.rb +14 -0
  19. data/lib/pwnlib/shellcraft/generators/amd64/common/infloop.rb +17 -0
  20. data/lib/pwnlib/shellcraft/generators/amd64/common/memcpy.rb +31 -0
  21. data/lib/pwnlib/shellcraft/generators/amd64/common/mov.rb +127 -0
  22. data/lib/pwnlib/shellcraft/generators/amd64/common/nop.rb +16 -0
  23. data/lib/pwnlib/shellcraft/generators/amd64/common/popad.rb +27 -0
  24. data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr.rb +64 -0
  25. data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr_array.rb +19 -0
  26. data/lib/pwnlib/shellcraft/generators/amd64/common/ret.rb +32 -0
  27. data/lib/pwnlib/shellcraft/generators/amd64/common/setregs.rb +19 -0
  28. data/lib/pwnlib/shellcraft/generators/amd64/linux/execve.rb +21 -0
  29. data/lib/pwnlib/shellcraft/generators/amd64/linux/linux.rb +14 -0
  30. data/lib/pwnlib/shellcraft/generators/amd64/linux/ls.rb +19 -0
  31. data/lib/pwnlib/shellcraft/generators/amd64/linux/sh.rb +19 -0
  32. data/lib/pwnlib/shellcraft/generators/amd64/linux/syscall.rb +21 -0
  33. data/lib/pwnlib/shellcraft/generators/helper.rb +106 -0
  34. data/lib/pwnlib/shellcraft/generators/i386/common/common.rb +14 -0
  35. data/lib/pwnlib/shellcraft/generators/i386/common/infloop.rb +17 -0
  36. data/lib/pwnlib/shellcraft/generators/i386/common/mov.rb +90 -0
  37. data/lib/pwnlib/shellcraft/generators/i386/common/nop.rb +16 -0
  38. data/lib/pwnlib/shellcraft/generators/i386/common/pushstr.rb +39 -0
  39. data/lib/pwnlib/shellcraft/generators/i386/common/pushstr_array.rb +19 -0
  40. data/lib/pwnlib/shellcraft/generators/i386/common/setregs.rb +19 -0
  41. data/lib/pwnlib/shellcraft/generators/i386/linux/execve.rb +19 -0
  42. data/lib/pwnlib/shellcraft/generators/i386/linux/linux.rb +14 -0
  43. data/lib/pwnlib/shellcraft/generators/i386/linux/ls.rb +19 -0
  44. data/lib/pwnlib/shellcraft/generators/i386/linux/sh.rb +19 -0
  45. data/lib/pwnlib/shellcraft/generators/i386/linux/syscall.rb +19 -0
  46. data/lib/pwnlib/shellcraft/generators/x86/common/common.rb +26 -0
  47. data/lib/pwnlib/shellcraft/generators/x86/common/infloop.rb +22 -0
  48. data/lib/pwnlib/shellcraft/generators/x86/common/mov.rb +15 -0
  49. data/lib/pwnlib/shellcraft/generators/x86/common/pushstr.rb +15 -0
  50. data/lib/pwnlib/shellcraft/generators/x86/common/pushstr_array.rb +85 -0
  51. data/lib/pwnlib/shellcraft/generators/x86/common/setregs.rb +82 -0
  52. data/lib/pwnlib/shellcraft/generators/x86/linux/execve.rb +69 -0
  53. data/lib/pwnlib/shellcraft/generators/x86/linux/linux.rb +14 -0
  54. data/lib/pwnlib/shellcraft/generators/x86/linux/ls.rb +66 -0
  55. data/lib/pwnlib/shellcraft/generators/x86/linux/sh.rb +52 -0
  56. data/lib/pwnlib/shellcraft/generators/x86/linux/syscall.rb +52 -0
  57. data/lib/pwnlib/shellcraft/registers.rb +145 -0
  58. data/lib/pwnlib/shellcraft/shellcraft.rb +67 -0
  59. data/lib/pwnlib/timer.rb +60 -0
  60. data/lib/pwnlib/tubes/buffer.rb +96 -0
  61. data/lib/pwnlib/tubes/sock.rb +95 -0
  62. data/lib/pwnlib/tubes/tube.rb +270 -0
  63. data/lib/pwnlib/util/cyclic.rb +95 -94
  64. data/lib/pwnlib/util/fiddling.rb +256 -220
  65. data/lib/pwnlib/util/getdents.rb +83 -0
  66. data/lib/pwnlib/util/hexdump.rb +109 -108
  67. data/lib/pwnlib/util/lists.rb +55 -0
  68. data/lib/pwnlib/util/packing.rb +226 -228
  69. data/lib/pwnlib/util/ruby.rb +18 -0
  70. data/lib/pwnlib/version.rb +2 -1
  71. data/test/abi_test.rb +21 -0
  72. data/test/asm_test.rb +104 -0
  73. data/test/constants/constant_test.rb +1 -0
  74. data/test/constants/constants_test.rb +4 -2
  75. data/test/context_test.rb +1 -0
  76. data/test/data/echo.rb +20 -0
  77. data/test/data/elfs/Makefile +22 -0
  78. data/test/data/elfs/amd64.frelro.elf +0 -0
  79. data/test/data/elfs/amd64.frelro.pie.elf +0 -0
  80. data/test/data/elfs/amd64.nrelro.elf +0 -0
  81. data/test/data/elfs/amd64.prelro.elf +0 -0
  82. data/test/data/elfs/i386.frelro.pie.elf +0 -0
  83. data/test/data/elfs/i386.prelro.elf +0 -0
  84. data/test/data/elfs/source.cpp +19 -0
  85. data/test/data/flag +1 -0
  86. data/test/data/lib32/ld.so.2 +0 -0
  87. data/test/data/lib32/libc.so.6 +0 -0
  88. data/test/data/lib64/ld.so.2 +0 -0
  89. data/test/data/lib64/libc.so.6 +0 -0
  90. data/test/dynelf_test.rb +59 -24
  91. data/test/elf/elf_test.rb +120 -0
  92. data/test/ext_test.rb +3 -2
  93. data/test/files/use_pwnlib.rb +1 -1
  94. data/test/logger_test.rb +61 -0
  95. data/test/memleak_test.rb +4 -33
  96. data/test/reg_sort_test.rb +3 -1
  97. data/test/shellcraft/infloop_test.rb +26 -0
  98. data/test/shellcraft/linux/ls_test.rb +108 -0
  99. data/test/shellcraft/linux/sh_test.rb +119 -0
  100. data/test/shellcraft/linux/syscalls/execve_test.rb +136 -0
  101. data/test/shellcraft/linux/syscalls/syscall_test.rb +83 -0
  102. data/test/shellcraft/memcpy_test.rb +35 -0
  103. data/test/shellcraft/mov_test.rb +98 -0
  104. data/test/shellcraft/nop_test.rb +26 -0
  105. data/test/shellcraft/popad_test.rb +29 -0
  106. data/test/shellcraft/pushstr_array_test.rb +91 -0
  107. data/test/shellcraft/pushstr_test.rb +108 -0
  108. data/test/shellcraft/registers_test.rb +32 -0
  109. data/test/shellcraft/ret_test.rb +30 -0
  110. data/test/shellcraft/setregs_test.rb +62 -0
  111. data/test/shellcraft/shellcraft_test.rb +28 -0
  112. data/test/test_helper.rb +12 -1
  113. data/test/timer_test.rb +23 -0
  114. data/test/tubes/buffer_test.rb +45 -0
  115. data/test/tubes/sock_test.rb +68 -0
  116. data/test/tubes/tube_test.rb +241 -0
  117. data/test/util/cyclic_test.rb +2 -1
  118. data/test/util/fiddling_test.rb +2 -1
  119. data/test/util/getdents_test.rb +32 -0
  120. data/test/util/hexdump_test.rb +7 -9
  121. data/test/util/lists_test.rb +21 -0
  122. data/test/util/packing_test.rb +4 -3
  123. metadata +215 -25
@@ -1,13 +1,14 @@
1
1
  # encoding: ASCII-8BIT
2
2
 
3
3
  require 'test_helper'
4
+
4
5
  require 'pwnlib/ext/array'
5
6
  require 'pwnlib/ext/integer'
6
7
  require 'pwnlib/ext/string'
7
8
 
8
9
  class ExtTest < MiniTest::Test
9
- # Thought that test one method in each module for each type is enough, since it's quite
10
- # stupid (and meaningless) to copy the list of proxied functions to here...
10
+ # Thought that test one method in each module for each type is enough, since it's quite stupid (and meaningless) to
11
+ # copy the list of proxied functions to here...
11
12
  def test_ext_string
12
13
  assert_equal(0x4142, 'AB'.u16(endian: 'be'))
13
14
  assert_equal([1, 1, 0, 0, 0, 1, 0, 0], "\xC4".bits)
@@ -8,7 +8,7 @@ require 'pwnlib/util/packing'
8
8
 
9
9
  raise 'call from module fail' unless ::Pwnlib::Util::Packing.p8(0x61) == 'a'
10
10
 
11
- include ::Pwnlib::Util::Packing::ClassMethods
11
+ include ::Pwnlib::Util::Packing
12
12
  raise 'include module and call fail' unless p8(0x61) == 'a'
13
13
 
14
14
  begin
@@ -0,0 +1,61 @@
1
+ # encoding: ASCII-8BIT
2
+
3
+ require 'test_helper'
4
+
5
+ require 'pwnlib/context'
6
+ require 'pwnlib/logger'
7
+
8
+ class LoggerTest < MiniTest::Test
9
+ include ::Pwnlib::Context
10
+ include ::Pwnlib::Logger
11
+
12
+ def setup
13
+ @logger = ::Pwnlib::Logger::LoggerType.new
14
+ class << @logger
15
+ def add(*args)
16
+ clear
17
+ super
18
+ @logdev.string
19
+ end
20
+
21
+ def indented(*args)
22
+ clear
23
+ super(*args)
24
+ @logdev.string
25
+ end
26
+
27
+ def clear
28
+ @logdev = StringIO.new
29
+ end
30
+ end
31
+ end
32
+
33
+ def test_log
34
+ str = 'darkhh i4 so s4d'
35
+ context.local(log_level: DEBUG) do
36
+ %w(DEBUG INFO WARN ERROR FATAL).each do |type|
37
+ assert_equal("[#{type}] #{str}\n", @logger.public_send(type.downcase, str))
38
+ assert_equal("[#{type}] #{str}\n", @logger.public_send(type.downcase) { str })
39
+ end
40
+ end
41
+
42
+ assert_empty(@logger.debug(str))
43
+ assert_empty(@logger.debug { str })
44
+ %w(INFO WARN ERROR FATAL).each do |type|
45
+ assert_equal("[#{type}] #{str}\n", @logger.public_send(type.downcase, str))
46
+ assert_equal("[#{type}] #{str}\n", @logger.public_send(type.downcase) { str })
47
+ end
48
+ end
49
+
50
+ def test_indented
51
+ assert_silent { log.indented('darkhh', level: DEBUG) }
52
+ assert_empty(@logger.indented('A', level: DEBUG))
53
+
54
+ data = ['meow', 'meow meow', 'meowmeowmeow'].join("\n")
55
+ assert_equal(<<-EOS, @logger.indented(data, level: INFO))
56
+ meow
57
+ meow meow
58
+ meowmeowmeow
59
+ EOS
60
+ end
61
+ end
@@ -5,44 +5,15 @@ require 'open3'
5
5
  require 'tty-platform'
6
6
 
7
7
  require 'test_helper'
8
+
8
9
  require 'pwnlib/memleak'
9
10
 
10
11
  class MemLeakTest < MiniTest::Test
11
12
  def setup
12
- @victim = IO.binread(File.expand_path('../data/victim32', __FILE__))
13
+ @victim = IO.binread(File.expand_path('data/victim32', __dir__))
13
14
  @leak = ::Pwnlib::MemLeak.new { |addr| @victim[addr] }
14
15
  end
15
16
 
16
- def test_find_elf_base_basic
17
- assert_equal(0, @leak.find_elf_base(@victim.length * 2 / 3))
18
- end
19
-
20
- def test_find_elf_base_running
21
- skip 'Only tested on linux' unless TTY::Platform.new.linux?
22
- [32, 64].each do |b|
23
- # TODO(hh): Use process instead of popen2
24
- Open3.popen2(File.expand_path("../data/victim#{b}", __FILE__)) do |i, o, t|
25
- main_ra = o.readline[2...-1].to_i(16)
26
- realbase = nil
27
- IO.readlines("/proc/#{t.pid}/maps").map(&:split).each do |s|
28
- st, ed = s[0].split('-').map { |x| x.to_i(16) }
29
- next unless main_ra.between?(st, ed)
30
- realbase = st
31
- break
32
- end
33
- refute_nil(realbase)
34
- mem = open("/proc/#{t.pid}/mem", 'rb')
35
- l2 = ::Pwnlib::MemLeak.new do |addr|
36
- mem.seek(addr)
37
- mem.getc
38
- end
39
- assert_equal(realbase, l2.find_elf_base(main_ra))
40
- mem.close
41
- i.write('bye')
42
- end
43
- end
44
- end
45
-
46
17
  def test_n
47
18
  assert_equal("\x7fELF", @leak.n(0, 4))
48
19
  assert_equal(@victim[0xf0, 0x20], @leak.n(0xf0, 0x20))
@@ -50,8 +21,8 @@ class MemLeakTest < MiniTest::Test
50
21
  end
51
22
 
52
23
  def test_b
53
- assert_equal(@victim[0x100], @leak.b(0x100))
54
- assert_equal(@victim[514], @leak.b(514))
24
+ assert_equal(::Pwnlib::Util::Packing.u8(@victim[0x100]), @leak.b(0x100))
25
+ assert_equal(::Pwnlib::Util::Packing.u8(@victim[514]), @leak.b(514))
55
26
  end
56
27
 
57
28
  def test_w
@@ -1,9 +1,11 @@
1
1
  # encoding: ASCII-8BIT
2
+
2
3
  require 'test_helper'
4
+
3
5
  require 'pwnlib/reg_sort'
4
6
 
5
7
  class RegSortTest < MiniTest::Test
6
- include ::Pwnlib::RegSort::ClassMethods
8
+ include ::Pwnlib::RegSort
7
9
 
8
10
  def setup
9
11
  @regs = %w(a b c d x y z)
@@ -0,0 +1,26 @@
1
+ # encoding: ASCII-8BIT
2
+
3
+ require 'test_helper'
4
+
5
+ require 'pwnlib/context'
6
+ require 'pwnlib/shellcraft/shellcraft'
7
+
8
+ class InfloopTest < MiniTest::Test
9
+ include ::Pwnlib::Context
10
+
11
+ def setup
12
+ @shellcraft = ::Pwnlib::Shellcraft::Shellcraft.instance
13
+ end
14
+
15
+ def test_amd64
16
+ context.local(arch: 'amd64') do
17
+ assert_match(/\Ainfloop_\d+:\n jmp infloop_\d+\n\Z/, @shellcraft.infloop)
18
+ end
19
+ end
20
+
21
+ def test_i386
22
+ context.local(arch: 'i386') do
23
+ assert_match(/\Ainfloop_\d+:\n jmp infloop_\d+\n\Z/, @shellcraft.infloop)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,108 @@
1
+ # encoding: ASCII-8BIT
2
+
3
+ require 'test_helper'
4
+
5
+ require 'pwnlib/context'
6
+ require 'pwnlib/shellcraft/shellcraft'
7
+
8
+ class LsTest < MiniTest::Test
9
+ include ::Pwnlib::Context
10
+
11
+ def setup
12
+ @shellcraft = ::Pwnlib::Shellcraft::Shellcraft.instance
13
+ end
14
+
15
+ def test_amd64
16
+ context.local(arch: 'amd64') do
17
+ assert_equal(<<-'EOS', @shellcraft.ls)
18
+ /* push ".\x00" */
19
+ push 0x2e
20
+ /* call open("rsp", 0, 0) */
21
+ push 2 /* (SYS_open) */
22
+ pop rax
23
+ mov rdi, rsp
24
+ xor esi, esi /* 0 */
25
+ cdq /* rdx=0 */
26
+ syscall
27
+ /* call getdents("rax", "rsp", 4096) */
28
+ mov rdi, rax
29
+ push 0x4e /* (SYS_getdents) */
30
+ pop rax
31
+ mov rsi, rsp
32
+ xor edx, edx
33
+ mov dh, 0x1000 >> 8
34
+ syscall
35
+ /* call write(1, "rsp", "rax") */
36
+ push 1
37
+ pop rdi
38
+ mov rsi, rsp
39
+ mov rdx, rax
40
+ push 1 /* (SYS_write) */
41
+ pop rax
42
+ syscall
43
+ EOS
44
+ assert_equal(<<-'EOS', @shellcraft.ls('/usr/bin'))
45
+ /* push "/usr/bin\x00" */
46
+ push 1
47
+ dec byte ptr [rsp]
48
+ mov rax, 0x6e69622f7273752f
49
+ push rax
50
+ /* call open("rsp", 0, 0) */
51
+ push 2 /* (SYS_open) */
52
+ pop rax
53
+ mov rdi, rsp
54
+ xor esi, esi /* 0 */
55
+ cdq /* rdx=0 */
56
+ syscall
57
+ /* call getdents("rax", "rsp", 4096) */
58
+ mov rdi, rax
59
+ push 0x4e /* (SYS_getdents) */
60
+ pop rax
61
+ mov rsi, rsp
62
+ xor edx, edx
63
+ mov dh, 0x1000 >> 8
64
+ syscall
65
+ /* call write(1, "rsp", "rax") */
66
+ push 1
67
+ pop rdi
68
+ mov rsi, rsp
69
+ mov rdx, rax
70
+ push 1 /* (SYS_write) */
71
+ pop rax
72
+ syscall
73
+ EOS
74
+ end
75
+ end
76
+
77
+ def test_i386
78
+ context.local(arch: 'i386') do
79
+ assert_equal(<<-'EOS', @shellcraft.ls)
80
+ /* push ".\x00" */
81
+ push 0x2e
82
+ /* call open("esp", 0, 0) */
83
+ push 5 /* (SYS_open) */
84
+ pop eax
85
+ mov ebx, esp
86
+ xor ecx, ecx /* 0 */
87
+ cdq /* edx=0 */
88
+ int 0x80
89
+ /* call getdents("eax", "esp", 4096) */
90
+ mov ebx, eax
91
+ xor eax, eax
92
+ mov al, 0x8d /* (SYS_getdents) */
93
+ mov ecx, esp
94
+ xor edx, edx
95
+ mov dh, 0x1000 >> 8
96
+ int 0x80
97
+ /* call write(1, "esp", "eax") */
98
+ push 1
99
+ pop ebx
100
+ mov ecx, esp
101
+ mov edx, eax
102
+ push 4 /* (SYS_write) */
103
+ pop eax
104
+ int 0x80
105
+ EOS
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,119 @@
1
+ # encoding: ASCII-8BIT
2
+
3
+ require 'test_helper'
4
+
5
+ require 'pwnlib/context'
6
+ require 'pwnlib/shellcraft/shellcraft'
7
+
8
+ class ShTest < MiniTest::Test
9
+ include ::Pwnlib::Context
10
+
11
+ def setup
12
+ @shellcraft = ::Pwnlib::Shellcraft::Shellcraft.instance
13
+ end
14
+
15
+ def test_amd64
16
+ context.local(arch: 'amd64') do
17
+ assert_equal(<<-'EOS', @shellcraft.sh)
18
+ /* push "/bin///sh\x00" */
19
+ push 0x68
20
+ mov rax, 0x732f2f2f6e69622f
21
+ push rax
22
+
23
+ /* call execve("rsp", 0, 0) */
24
+ push 0x3b /* (SYS_execve) */
25
+ pop rax
26
+ mov rdi, rsp
27
+ xor esi, esi /* 0 */
28
+ cdq /* rdx=0 */
29
+ syscall
30
+ EOS
31
+ assert_equal(<<-'EOS', @shellcraft.sh(argv: true))
32
+ /* push argument array ["sh\x00"] */
33
+ /* push "sh\x00" */
34
+ push 0x1010101 ^ 0x6873
35
+ xor dword ptr [rsp], 0x1010101
36
+ xor esi, esi /* 0 */
37
+ push rsi /* null terminate */
38
+ push 8
39
+ pop rsi
40
+ add rsi, rsp
41
+ push rsi /* "sh\x00" */
42
+ mov rsi, rsp
43
+
44
+ /* push "/bin///sh\x00" */
45
+ push 0x68
46
+ mov rax, 0x732f2f2f6e69622f
47
+ push rax
48
+
49
+ /* call execve("rsp", "rsi", 0) */
50
+ push 0x3b /* (SYS_execve) */
51
+ pop rax
52
+ mov rdi, rsp
53
+ cdq /* rdx=0 */
54
+ syscall
55
+ EOS
56
+ assert_equal(<<-'EOS', @shellcraft.sh(argv: ['sh', '-c', 'echo pusheen']))
57
+ /* push argument array ["sh\x00", "-c\x00", "echo pusheen\x00"] */
58
+ /* push "sh\x00-c\x00echo pusheen\x00" */
59
+ push 0x1010101 ^ 0x6e65
60
+ xor dword ptr [rsp], 0x1010101
61
+ mov rax, 0x6568737570206f68
62
+ push rax
63
+ mov rax, 0x101010101010101
64
+ push rax
65
+ mov rax, 0x626401622c016972 /* 0x101010101010101 ^ 0x636500632d006873 */
66
+ xor [rsp], rax
67
+ xor esi, esi /* 0 */
68
+ push rsi /* null terminate */
69
+ push 0xe
70
+ pop rsi
71
+ add rsi, rsp
72
+ push rsi /* "echo pusheen\x00" */
73
+ push 0x13
74
+ pop rsi
75
+ add rsi, rsp
76
+ push rsi /* "-c\x00" */
77
+ push 0x18
78
+ pop rsi
79
+ add rsi, rsp
80
+ push rsi /* "sh\x00" */
81
+ mov rsi, rsp
82
+
83
+ /* push "/bin///sh\x00" */
84
+ push 0x68
85
+ mov rax, 0x732f2f2f6e69622f
86
+ push rax
87
+
88
+ /* call execve("rsp", "rsi", 0) */
89
+ push 0x3b /* (SYS_execve) */
90
+ pop rax
91
+ mov rdi, rsp
92
+ cdq /* rdx=0 */
93
+ syscall
94
+ EOS
95
+ end
96
+ end
97
+
98
+ def test_i386
99
+ context.local(arch: 'i386') do
100
+ assert_equal(<<-'EOS', @shellcraft.sh)
101
+ /* push "/bin///sh\x00" */
102
+ push 0x68
103
+ push 0x732f2f2f
104
+ push 0x6e69622f
105
+
106
+ /* call execve("esp", 0, 0) */
107
+ push 0xb /* (SYS_execve) */
108
+ pop eax
109
+ mov ebx, esp
110
+ xor ecx, ecx /* 0 */
111
+ cdq /* edx=0 */
112
+ int 0x80
113
+ EOS
114
+ assert_equal(@shellcraft.execve('/bin///sh', ['sh'], 0), @shellcraft.sh(argv: true))
115
+ assert_equal(@shellcraft.execve('/bin///sh', ['sh', '-c', 'echo pusheen'], 0),
116
+ @shellcraft.sh(argv: ['sh', '-c', 'echo pusheen']))
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,136 @@
1
+ # encoding: ASCII-8BIT
2
+
3
+ require 'test_helper'
4
+
5
+ require 'pwnlib/context'
6
+ require 'pwnlib/shellcraft/shellcraft'
7
+
8
+ class ExecveTest < MiniTest::Test
9
+ include ::Pwnlib::Context
10
+
11
+ def setup
12
+ @shellcraft = ::Pwnlib::Shellcraft::Shellcraft.instance
13
+ end
14
+
15
+ def test_amd64
16
+ context.local(arch: 'amd64') do
17
+ assert_equal(<<-'EOS', @shellcraft.execve('/bin///sh', 0, nil))
18
+ /* push "/bin///sh\x00" */
19
+ push 0x68
20
+ mov rax, 0x732f2f2f6e69622f
21
+ push rax
22
+
23
+ /* call execve("rsp", 0, 0) */
24
+ push 0x3b /* (SYS_execve) */
25
+ pop rax
26
+ mov rdi, rsp
27
+ xor esi, esi /* 0 */
28
+ cdq /* rdx=0 */
29
+ syscall
30
+ EOS
31
+ assert_equal(<<-'EOS', @shellcraft.execve('rax', ['sh'], PWD: '.'))
32
+ /* push argument array ["sh\x00"] */
33
+ /* push "sh\x00" */
34
+ push 0x1010101 ^ 0x6873
35
+ xor dword ptr [rsp], 0x1010101
36
+ xor esi, esi /* 0 */
37
+ push rsi /* null terminate */
38
+ push 8
39
+ pop rsi
40
+ add rsi, rsp
41
+ push rsi /* "sh\x00" */
42
+ mov rsi, rsp
43
+
44
+ /* push argument array ["PWD=.\x00"] */
45
+ /* push "PWD=.\x00" */
46
+ mov rax, 0x101010101010101
47
+ push rax
48
+ mov rax, 0x101012f3c455651 /* 0x101010101010101 ^ 0x2e3d445750 */
49
+ xor [rsp], rax
50
+ xor edx, edx /* 0 */
51
+ push rdx /* null terminate */
52
+ push 8
53
+ pop rdx
54
+ add rdx, rsp
55
+ push rdx /* "PWD=.\x00" */
56
+ mov rdx, rsp
57
+
58
+ /* call execve("rax", "rsi", "rdx") */
59
+ mov rdi, rax
60
+ push 0x3b /* (SYS_execve) */
61
+ pop rax
62
+ syscall
63
+ EOS
64
+ assert_equal(<<-'EOS', @shellcraft.execve('rdi', 'rsi', 'rdx'))
65
+ /* call execve("rdi", "rsi", "rdx") */
66
+ push 0x3b /* (SYS_execve) */
67
+ pop rax
68
+ syscall
69
+ EOS
70
+ err = assert_raises(ArgumentError) { @shellcraft.execve('rdi', 'rdi', 'xdd') }
71
+ assert_match(/not a valid register/, err.message)
72
+ err = assert_raises(ArgumentError) { @shellcraft.execve('rdi', 'qqpie', 'rdi') }
73
+ assert_match(/not a valid register/, err.message)
74
+ end
75
+ end
76
+
77
+ def test_i386
78
+ context.local(arch: 'i386') do
79
+ assert_equal(<<-'EOS', @shellcraft.execve('/bin///sh', 0, nil))
80
+ /* push "/bin///sh\x00" */
81
+ push 0x68
82
+ push 0x732f2f2f
83
+ push 0x6e69622f
84
+
85
+ /* call execve("esp", 0, 0) */
86
+ push 0xb /* (SYS_execve) */
87
+ pop eax
88
+ mov ebx, esp
89
+ xor ecx, ecx /* 0 */
90
+ cdq /* edx=0 */
91
+ int 0x80
92
+ EOS
93
+ assert_equal(<<-'EOS', @shellcraft.execve('eax', ['sh'], PWD: '.'))
94
+ /* push argument array ["sh\x00"] */
95
+ /* push "sh\x00" */
96
+ push 0x1010101
97
+ xor dword ptr [esp], 0x1016972 /* 0x1010101 ^ 0x6873 */
98
+ xor ecx, ecx /* 0 */
99
+ push ecx /* null terminate */
100
+ push 4
101
+ pop ecx
102
+ add ecx, esp
103
+ push ecx /* "sh\x00" */
104
+ mov ecx, esp
105
+
106
+ /* push argument array ["PWD=.\x00"] */
107
+ /* push "PWD=.\x00" */
108
+ push 0x2e
109
+ push 0x3d445750
110
+ xor edx, edx /* 0 */
111
+ push edx /* null terminate */
112
+ push 4
113
+ pop edx
114
+ add edx, esp
115
+ push edx /* "PWD=.\x00" */
116
+ mov edx, esp
117
+
118
+ /* call execve("eax", "ecx", "edx") */
119
+ mov ebx, eax
120
+ push 0xb /* (SYS_execve) */
121
+ pop eax
122
+ int 0x80
123
+ EOS
124
+ assert_equal(<<-'EOS', @shellcraft.execve('ebx', 'ecx', 'edx'))
125
+ /* call execve("ebx", "ecx", "edx") */
126
+ push 0xb /* (SYS_execve) */
127
+ pop eax
128
+ int 0x80
129
+ EOS
130
+ err = assert_raises(ArgumentError) { @shellcraft.execve('edi', 'esi', 'xdd') }
131
+ assert_match(/not a valid register/, err.message)
132
+ err = assert_raises(ArgumentError) { @shellcraft.execve('edi', 'qqpie', 'edi') }
133
+ assert_match(/not a valid register/, err.message)
134
+ end
135
+ end
136
+ end