rubypwn 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/source/elf.rst +30 -7
- data/lib/elf.rb +119 -97
- data/rubypwn.gemspec +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c0d72fc09f9d7adca8c1e58494f061c2901d9cf
|
4
|
+
data.tar.gz: aadbaee90c0108328029d26591102a21f9933305
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93d38f069c3aeb10fe0fb5a0c8fc973c6b502259e666b7ac7852fa39aa551893a2c6f8c6376d2d3d8189f0b3c180a533611754212439dee124b4eba88f5b6bbf
|
7
|
+
data.tar.gz: f8ce8a3d75a3233bb100e68e679e475b468aafa518bef24ccebcdae7decd8a42936c32a5b409ef98f75ee86259a870893e5190c381edae0b5eb372a68ecef406
|
data/docs/source/elf.rst
CHANGED
@@ -3,12 +3,35 @@ class Elf
|
|
3
3
|
|
4
4
|
Used to get some constant value from the binary::
|
5
5
|
|
6
|
+
2.2.0 :001 > require 'pp'
|
6
7
|
2.2.0 :001 > require 'rubypwn'
|
7
8
|
=> true
|
8
|
-
2.2.0 :002 > e = Elf.new "
|
9
|
-
2.2.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
2.2.0 :002 > e = Elf.new "traveller"
|
10
|
+
2.2.2 :005 > pp Elf.new "traveller"
|
11
|
+
#<Elf:0x007fdd23c3b510
|
12
|
+
@arch="x86",
|
13
|
+
@bits=32,
|
14
|
+
@dynamic=
|
15
|
+
{"strtab"=>134513496,
|
16
|
+
"symtab"=>134513160,
|
17
|
+
"rel_type"=>"REL",
|
18
|
+
"jmprel"=>134513844},
|
19
|
+
@global={"__gmon_start__"=>{"offset"=>134521192, "value"=>0}},
|
20
|
+
@got=
|
21
|
+
{"__errno_location"=>134521208,
|
22
|
+
"sigemptyset"=>134521212,
|
23
|
+
"getpid"=>134521216,
|
24
|
+
"__gmon_start__"=>134521220,
|
25
|
+
"__isoc99_sscanf"=>134521224,
|
26
|
+
"fgets"=>134521228,
|
27
|
+
"__libc_start_main"=>134521232,
|
28
|
+
"sigaltstack"=>134521236,
|
29
|
+
"siglongjmp"=>134521240,
|
30
|
+
"sigaction"=>134521244,
|
31
|
+
"strlen"=>134521248,
|
32
|
+
"printf"=>134521252,
|
33
|
+
"setvbuf"=>134521256,
|
34
|
+
"puts"=>134521260,
|
35
|
+
"kill"=>134521264,
|
36
|
+
"__sigsetjmp"=>134521268,
|
37
|
+
"exit"=>134521272}>
|
data/lib/elf.rb
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
require 'bindata'
|
2
2
|
|
3
|
+
class Dynamic32 < BinData::Record
|
4
|
+
endian :little
|
5
|
+
int32 :d_tag
|
6
|
+
uint32 :d_val
|
7
|
+
end
|
8
|
+
|
9
|
+
class Dynamic64 < BinData::Record
|
10
|
+
endian :little
|
11
|
+
int64 :d_tag
|
12
|
+
uint64 :d_val
|
13
|
+
end
|
14
|
+
|
3
15
|
class Symtab32 < BinData::Record
|
4
16
|
endian :little
|
5
17
|
int32 :st_name #/* Symbol name (string tbl index) */
|
@@ -87,6 +99,7 @@ class Relaplt64 < BinData::Record
|
|
87
99
|
r_info & 0xffffffff
|
88
100
|
end
|
89
101
|
end
|
102
|
+
|
90
103
|
class ElfParser < BinData::Record
|
91
104
|
endian :little
|
92
105
|
# magic number
|
@@ -126,26 +139,7 @@ class ElfParser < BinData::Record
|
|
126
139
|
# Section header string table index
|
127
140
|
int16 :e_shstrndx
|
128
141
|
skip :length => lambda{e_shoff - e_ehsize}
|
129
|
-
|
130
|
-
#array :ph, :initial_length => :e_phnum do
|
131
|
-
#int32 :p_type
|
132
|
-
## Segment bit mask (RWX)
|
133
|
-
#int32 :p_flags
|
134
|
-
## Segment file offset
|
135
|
-
#choice :p_offset, :selection => lambda{e_ident.ei_class}, :choices => {1 => :int32le, 2 => :int64le}
|
136
|
-
## Segment virtual address
|
137
|
-
#choice :p_vaddr, :selection => lambda{e_ident.ei_class}, :choices => {1 => :int32le, 2 => :int64le}
|
138
|
-
## Segment physical address
|
139
|
-
#choice :p_paddr, :selection => lambda{e_ident.ei_class}, :choices => {1 => :int32le, 2 => :int64le}
|
140
|
-
## Segment size in file
|
141
|
-
#choice :p_filesz, :selection => lambda{e_ident.ei_class}, :choices => {1 => :int32le, 2 => :int64le}
|
142
|
-
## Segment size in memory
|
143
|
-
#choice :p_memsz, :selection => lambda{e_ident.ei_class}, :choices => {1 => :int32le, 2 => :int64le}
|
144
|
-
## Segment alignment
|
145
|
-
#choice :p_align, :selection => lambda{e_ident.ei_class}, :choices => {1 => :int32le, 2 => :int64le}
|
146
|
-
##string :p_segment, :read_length => lambda{p_filesz - e_phentsize}
|
147
|
-
#end
|
148
|
-
# Contains index of the section header tab entry that contains the section names.
|
142
|
+
|
149
143
|
array :sh, :initial_length => lambda{e_shnum} do
|
150
144
|
# Section name (string tbl index)
|
151
145
|
int32 :sh_name
|
@@ -179,22 +173,6 @@ class ElfParser < BinData::Record
|
|
179
173
|
array 1, :type => :symtab32, :initial_length => 0
|
180
174
|
array 2, :type => :symtab64, :initial_length => 0
|
181
175
|
end
|
182
|
-
choice :relplt, :selection => lambda{e_ident.ei_class} do
|
183
|
-
array 1, :type => :relplt32, :initial_length => 0
|
184
|
-
array 2, :type => :relplt64, :initial_length => 0
|
185
|
-
end
|
186
|
-
choice :relaplt, :selection => lambda{e_ident.ei_class} do
|
187
|
-
array 1, :type => :relaplt32, :initial_length => 0
|
188
|
-
array 2, :type => :relaplt64, :initial_length => 0
|
189
|
-
end
|
190
|
-
choice :reldyn, :selection => lambda{e_ident.ei_class} do
|
191
|
-
array 1, :type => :relplt32, :initial_length => 0
|
192
|
-
array 2, :type => :relplt64, :initial_length => 0
|
193
|
-
end
|
194
|
-
choice :reladyn, :selection => lambda{e_ident.ei_class} do
|
195
|
-
array 1, :type => :relaplt32, :initial_length => 0
|
196
|
-
array 2, :type => :relaplt64, :initial_length => 0
|
197
|
-
end
|
198
176
|
|
199
177
|
def parse_bits(ei_class)
|
200
178
|
ei_class == 1 ? 32 : 64
|
@@ -292,24 +270,34 @@ class ElfParser < BinData::Record
|
|
292
270
|
end
|
293
271
|
|
294
272
|
class Elf
|
295
|
-
attr_accessor :gotplt
|
273
|
+
#attr_accessor :gotplt
|
274
|
+
attr_accessor :arch, :bits, :dynamic, :got, :global
|
296
275
|
|
297
276
|
def initialize(file)
|
298
277
|
# To avoid unicode
|
299
278
|
binary = File.read(file).force_encoding('binary')
|
300
279
|
# To fix bugs leading eof, that's why here is a newline ...
|
301
|
-
|
302
|
-
#
|
303
|
-
|
304
|
-
# parse symbol table
|
305
|
-
parse_symtab binary, @elf
|
306
|
-
# parse rel.plt
|
307
|
-
parse_relplt binary, @elf
|
308
|
-
@gotplt = gen_gotplt @elf
|
280
|
+
elf = ElfParser.read binary + "\n"
|
281
|
+
# parse information we need
|
282
|
+
extract_info binary, elf
|
309
283
|
end
|
310
284
|
|
311
285
|
private
|
312
|
-
|
286
|
+
|
287
|
+
def extract_info(binary, elf)
|
288
|
+
@arch = elf.arch.to_s
|
289
|
+
@bits = elf.bits.to_i
|
290
|
+
# parse section name
|
291
|
+
parse_section_name binary, elf
|
292
|
+
# parse symbol table
|
293
|
+
parse_symtab binary, elf
|
294
|
+
# Parse dynamic section
|
295
|
+
parse_dynamic_constant binary, elf
|
296
|
+
## parse rel.plt
|
297
|
+
parse_relplt binary, elf
|
298
|
+
end
|
299
|
+
|
300
|
+
def parse_section_name(binary, elf)
|
313
301
|
strtab_offset = elf.sh[elf.e_shstrndx].sh_offset.to_i
|
314
302
|
strtab = binary[(strtab_offset)..-1]
|
315
303
|
elf.e_shnum.times do |i|
|
@@ -318,6 +306,42 @@ class Elf
|
|
318
306
|
end
|
319
307
|
end
|
320
308
|
|
309
|
+
def parse_dynamic_constant(binary, elf)
|
310
|
+
dynamic = nil
|
311
|
+
elf.e_shnum.times do |i|
|
312
|
+
content = binary[elf.sh[i].sh_offset, elf.sh[i].sh_size]
|
313
|
+
if elf.sh[i].sh_type == 6 # DYNAMIC
|
314
|
+
size = elf.sh[i].sh_size / elf.sh[i].sh_entsize
|
315
|
+
if @bits == 32
|
316
|
+
dynamic = BinData::Array.new(:type => :dynamic32, :initial_length => size)
|
317
|
+
else
|
318
|
+
dynamic = BinData::Array.new(:type => :dynamic64, :initial_length => size)
|
319
|
+
end
|
320
|
+
dynamic.read content
|
321
|
+
end
|
322
|
+
end
|
323
|
+
@dynamic = {}
|
324
|
+
dynamic.each do |d|
|
325
|
+
# PLTREL
|
326
|
+
if d.d_tag == 20
|
327
|
+
if d.d_val == 7
|
328
|
+
@dynamic["rel_type"]= "RELA"
|
329
|
+
elsif d.d_val == 17
|
330
|
+
@dynamic["rel_type"]= "REL"
|
331
|
+
end
|
332
|
+
# STRTAB
|
333
|
+
elsif d.d_tag == 5
|
334
|
+
@dynamic["strtab"]= d.d_val.to_i
|
335
|
+
# SYMTAB
|
336
|
+
elsif d.d_tag == 6
|
337
|
+
@dynamic["symtab"]= d.d_val.to_i
|
338
|
+
# JMPREL
|
339
|
+
elsif d.d_tag == 0x17
|
340
|
+
@dynamic["jmprel"]= d.d_val.to_i
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
321
345
|
def parse_symtab(binary, elf)
|
322
346
|
# find dynamic symtab
|
323
347
|
symtab = nil
|
@@ -350,67 +374,65 @@ class Elf
|
|
350
374
|
end
|
351
375
|
|
352
376
|
def parse_relplt(binary, elf)
|
353
|
-
|
377
|
+
rel = nil
|
378
|
+
reldyn = nil
|
354
379
|
elf.e_shnum.times do |i|
|
355
|
-
if
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
size = elf.sh[i].sh_size/elf.sh[i].sh_entsize
|
373
|
-
if elf.e_ident[:ei_class] == 1
|
374
|
-
plt = BinData::Array.new(:type => :relaplt32, :initial_length => size)
|
375
|
-
else
|
376
|
-
plt = BinData::Array.new(:type => :relaplt64, :initial_length => size)
|
380
|
+
if @dynamic["rel_type"] == "REL"
|
381
|
+
if elf.sh[i].name_str == ".rel.plt"
|
382
|
+
size = elf.sh[i].sh_size/elf.sh[i].sh_entsize
|
383
|
+
if elf.e_ident[:ei_class] == 1
|
384
|
+
rel = BinData::Array.new(:type => :relplt32, :initial_length => size)
|
385
|
+
else
|
386
|
+
rel = BinData::Array.new(:type => :relplt64, :initial_length => size)
|
387
|
+
end
|
388
|
+
rel.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size]
|
389
|
+
elsif elf.sh[i].name_str == ".rel.dyn"
|
390
|
+
size = elf.sh[i].sh_size/elf.sh[i].sh_entsize
|
391
|
+
if @bits == 32
|
392
|
+
reldyn = BinData::Array.new(:type => :relplt32, :initial_length => size)
|
393
|
+
else
|
394
|
+
reldyn = BinData::Array.new(:type => :relplt64, :initial_length => size)
|
395
|
+
end
|
396
|
+
reldyn.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size]
|
377
397
|
end
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
398
|
+
elsif @dynamic["rel_type"] == "RELA"
|
399
|
+
if elf.sh[i].name_str == ".rela.plt"
|
400
|
+
size = elf.sh[i].sh_size/elf.sh[i].sh_entsize
|
401
|
+
if @bits == 32
|
402
|
+
rel = BinData::Array.new(:type => :relaplt32, :initial_length => size)
|
403
|
+
else
|
404
|
+
rel = BinData::Array.new(:type => :relaplt64, :initial_length => size)
|
405
|
+
end
|
406
|
+
rel.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size]
|
407
|
+
elsif elf.sh[i].name_str == ".rela.dyn"
|
408
|
+
size = elf.sh[i].sh_size/elf.sh[i].sh_entsize
|
409
|
+
if @bits == 32
|
410
|
+
reldyn = BinData::Array.new(:type => :relaplt32, :initial_length => size)
|
411
|
+
else
|
412
|
+
reldyn = BinData::Array.new(:type => :relaplt64, :initial_length => size)
|
413
|
+
end
|
414
|
+
reldyn.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size]
|
385
415
|
end
|
386
|
-
elf.reladyn.assign plt.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size]
|
387
416
|
end
|
388
417
|
end
|
389
|
-
end
|
390
|
-
|
391
|
-
def gen_gotplt(elf)
|
392
|
-
result = {}
|
393
|
-
rel = nil
|
394
418
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
end
|
402
|
-
|
403
|
-
elf.reldyn.each do |r|
|
404
|
-
result[elf.symtab[r.sym_index.to_i].name_str.to_s] = elf.symtab[r.sym_index.to_i].st_value.to_i
|
419
|
+
# extract information
|
420
|
+
@got = {}
|
421
|
+
rel.each do |r|
|
422
|
+
if r.type.to_i == 7 # JMP_SLOT
|
423
|
+
@got[elf.symtab[r.sym_index.to_i].name_str.to_s] = r.r_offset.to_i
|
424
|
+
end
|
405
425
|
end
|
406
|
-
|
407
|
-
|
408
|
-
|
426
|
+
@global = Hash.new {|h, k| h[k] = Hash.new}
|
427
|
+
reldyn.each do |r|
|
428
|
+
if r.type.to_i == 6 # GLOB_DAT
|
429
|
+
@global[elf.symtab[r.sym_index.to_i].name_str.to_s]["offset"] = r.r_offset.to_i
|
430
|
+
@global[elf.symtab[r.sym_index.to_i].name_str.to_s]["value"] = elf.symtab[r.sym_index.to_i].st_value.to_i
|
431
|
+
end
|
409
432
|
end
|
410
|
-
result
|
411
433
|
end
|
412
434
|
end
|
413
435
|
|
414
436
|
#require 'pp'
|
415
437
|
#e = Elf.new ARGV[0]
|
416
|
-
#pp e
|
438
|
+
#pp e
|
data/rubypwn.gemspec
CHANGED