support of i386, tested on 16.04 and 14.04 lib32

This commit is contained in:
david942j 2017-02-13 23:06:20 +08:00
parent 77ed626dc1
commit 022a7c57f0
8 changed files with 94 additions and 1 deletions

View File

@ -1 +1,2 @@
libc-2.23-60131540dadc6796cab33388349e6e4e68692053
libc-2.23-926eb99d49cab2e5622af38ab07395f5b32035e9

View File

@ -0,0 +1,8 @@
require 'one_gadget/gadget'
# Ubuntu GLIBC 2.23-0ubuntu5
# ELF 32-bit LSB shared object, Intel 80386
build_id = File.basename(__FILE__, '.rb').split('-').last
rw_area_constraint = 'esi is the address of `rw-p` area of libc'
OneGadget::Gadget.add(build_id, 0x3ac69, constraints: [rw_area_constraint, '[esp+0x34] == NULL'])
OneGadget::Gadget.add(build_id, 0x5fbbe, constraints: [rw_area_constraint, 'eax == NULL'])
OneGadget::Gadget.add(build_id, 0x12036c, constraints: [rw_area_constraint, 'eax == NULL'])

View File

@ -54,7 +54,8 @@ module OneGadget
offset = lines.first.scan(/^([\da-f]+):/)[0][0].to_i(16)
# fetch those might be constraints lines.
important_lines = lines.select(&block).map do |line|
line.split("\t").last.gsub(/\s+/, ' ')
ar = line.split("\t")
"#{ar.first} #{ar.last.gsub(/\s+/, ' ')}"
end
OneGadget::Gadget::Gadget.new(offset, constraints: important_lines)
end

View File

@ -0,0 +1,54 @@
require 'one_gadget/fetchers/base'
module OneGadget
module Fetcher
# Fetcher for i386.
class I386 < OneGadget::Fetcher::Base
def find
rw_off = rw_offset
bin_sh = str_offset('/bin/sh')
minus_c = str_offset('-c')
rel_sh_hex = (rw_off - bin_sh).to_s(16)
rel_minus_c = (rw_off - minus_c).to_s(16)
cands = candidates do |candidate|
next false unless candidate.include?(rel_sh_hex)
true
end
# remove lines before and with -c appears
cands = slice_prefix(cands) do |line|
line.include?(rel_minus_c)
end
# special handle for execl call
cands.map! do |cand|
lines = cand.lines
next cand unless lines.last.include?('execl')
# Find the last three +push+, or mov [esp+0x8], .*
# Make it call +execl("/bin/sh", "sh", NULL)+.
if cand.include?('esp+0x8')
to_rm = lines.index { |c| c.include?('esp+0x8') }
else
push_cnt = 0
to_rm = lines.rindex do |c|
push_cnt += 1 if c.include?('push')
push_cnt >= 3
end
end
lines = lines[to_rm..-1] unless to_rm.nil?
lines.join
end
cands.map do |candidate|
convert_to_gadget(candidate) do |_|
true
end
end
end
private
def rw_offset
# How to find this offset correctly..?
line = `readelf -d #{file}|grep PLTGOT`
line.scan(/0x[\da-f]+/).last.to_i(16) & -0x1000
end
end
end
end

View File

@ -17,4 +17,9 @@ describe OneGadget::Helper do
it 'colorize' do
expect(OneGadget::Helper.colorize('123', sev: :integer)).to eq "\e[38;5;12m123\e[0m"
end
it 'architecture' do
expect(OneGadget::Helper.architecture(@libcpath)).to be :amd64
expect(OneGadget::Helper.architecture(__FILE__)).to be :unknown
end
end

View File

@ -0,0 +1,24 @@
require 'one_gadget'
describe 'one_gadget' do
before(:each) do
@build_id = '926eb99d49cab2e5622af38ab07395f5b32035e9'
@libcpath19 = File.join(File.dirname(__FILE__), 'data', 'libc-2.19-fd51b20e670e9a9f60dc3b06dc9761fb08c9358b.so')
@libcpath23 = File.join(File.dirname(__FILE__), 'data', 'libc-2.23-926eb99d49cab2e5622af38ab07395f5b32035e9.so')
end
it 'from file libc-2.19' do
expect(OneGadget.gadgets(file: @libcpath19, force_file: true)).to eq [0x3fd27, 0x64c60, 0x1244a6]
end
it 'from file libc-2.23' do
expect(OneGadget.gadgets(file: @libcpath23, force_file: true)).to eq [0x3ac69, 0x5fbbe, 0x12036c]
end
describe 'from build id' do
it 'normal' do
# only check not empty because the gadgets might add frequently.
expect(OneGadget.gadgets(build_id: @build_id)).not_to be_empty
end
end
end