unmangler 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ class StringPtr
4
+ attr_accessor :string, :pos
5
+
6
+ def initialize s=nil, pos=0
7
+ case s
8
+ when String
9
+ @string = s
10
+ @pos = pos
11
+ when StringPtr
12
+ @string = s.string
13
+ @pos = s.pos + pos
14
+ when NilClass
15
+ @string = nil
16
+ @pos = pos
17
+ else
18
+ raise "invalid s: #{s.inspect}"
19
+ end
20
+ end
21
+
22
+ def [] pos, len=nil
23
+ if t = @string[@pos..-1]
24
+ if len
25
+ t[pos, len]
26
+ else
27
+ t[pos]
28
+ end
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ def []= pos, x, y=nil
35
+ if y
36
+ # s[10, 3] = 'abc'
37
+ @string[@pos+pos, x] = y
38
+ elsif pos.is_a?(Range)
39
+ range = pos
40
+ if range.end > 0
41
+ # s[10..12] = 'abc'
42
+ @string[Range.new(range.begin+@pos, range.end+@pos)] = x
43
+ else
44
+ if range.begin >= 0
45
+ # s[10..-1] = 'abc'
46
+ @string[Range.new(range.begin+@pos, range.end)] = x
47
+ else
48
+ # s[-3..-1] = 'abc'
49
+ @string[range] = x
50
+ end
51
+ end
52
+ else
53
+ # s[10] = 'a'
54
+ @string[@pos+pos] = x
55
+ end
56
+ end
57
+
58
+ def << s
59
+ @string[@pos, s.size] = s
60
+ @pos += s.size
61
+ end
62
+
63
+ def index needle
64
+ @string[@pos..-1].index(needle)
65
+ end
66
+
67
+ def =~ re
68
+ @string[@pos..-1] =~ re
69
+ end
70
+
71
+ def inc!; @pos+=1; end
72
+ def dec!; @pos-=1; end
73
+
74
+ def trim!
75
+ return unless @string
76
+ if idx = @string.index("\x00")
77
+ @string[idx..-1] = ''
78
+ @pos = @string.size if @pos > @string.size
79
+ end
80
+ end
81
+
82
+ def + n
83
+ self.class.new @string, @pos+n
84
+ end
85
+
86
+ def - x
87
+ case x
88
+ when Numeric
89
+ # shift pointer
90
+ self.class.new @string, @pos-x
91
+ when StringPtr
92
+ # return diff btw 2 ptrs
93
+ raise "subtracting different pointers" if self.string != x.string
94
+ @pos - x.pos
95
+ end
96
+ end
97
+ end
98
+
99
+ if $0 == __FILE__
100
+ ptr = StringPtr.new("foo")
101
+ p ptr[0]
102
+ p ptr[1]
103
+ p ptr
104
+ ptr += 1
105
+ p ptr
106
+ p ptr[0]
107
+
108
+ p2 = ptr+4
109
+ p ptr-p2
110
+ p p2-ptr
111
+ p ptr-1
112
+ end
@@ -0,0 +1,3 @@
1
+ module Unmangler
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unmangler::Borland do
4
+
5
+ it "keeps original name if not mangled" do
6
+ s = "foo::bar(@)"
7
+ Unmangler::Borland.unmangle(s).should == s
8
+ end
9
+
10
+ describe "#unmangle" do
11
+ it "raises error on bad input" do
12
+ lambda{
13
+ Unmangler::Borland.unmangle("@TTabPage@$bctr")
14
+ }.should raise_error
15
+ end
16
+ end
17
+
18
+ describe "#safe_unmangle" do
19
+ it "raises no error and returns original on bad input" do
20
+ s = "@TTabPage@$bctr"
21
+ Unmangler::Borland.safe_unmangle(s).should == s
22
+ end
23
+ end
24
+
25
+ def self.check mangled, unmangled
26
+ it "unmangles #{mangled}" do
27
+ Unmangler::Borland.unmangle(mangled).should == unmangled
28
+ end
29
+
30
+ it "unmangles #{mangled} w/o args" do
31
+ x = unmangled.split('(').first.strip.sub(/^__fastcall /,'')
32
+ Unmangler::Borland.unmangle(mangled, :args => false).should == x
33
+ end
34
+ end
35
+
36
+ check "@afunc$qxzcupi", "afunc(const signed char, int *)"
37
+ check "@foo$qpqfi$d", "foo(double (*)(float, int))"
38
+ check "@myclass@func$qil","myclass::func(int, long)"
39
+
40
+ check "@Sysinit@@InitExe$qqrpv",
41
+ "__fastcall Sysinit::__linkproc__ InitExe(void *)"
42
+
43
+ check "@Forms@TApplication@SetTitle$qqrx17System@AnsiString",
44
+ "__fastcall Forms::TApplication::SetTitle(const System::AnsiString)"
45
+
46
+ check "@Forms@TApplication@CreateForm$qqrp17System@TMetaClasspv",
47
+ "__fastcall Forms::TApplication::CreateForm(System::TMetaClass *, void *)"
48
+
49
+ check "@System@@LStrCatN$qqrv", "__fastcall System::__linkproc__ LStrCatN()"
50
+
51
+ check "@System@DynArraySetLength$qqrrpvpvipi",
52
+ "__fastcall System::DynArraySetLength(void *&, void *, int, int *)"
53
+
54
+ check "@System@Variant@PutElement$qqrrx14System@Variantxixi",
55
+ "__fastcall System::Variant::PutElement(System::Variant&, const int, const int)"
56
+
57
+ check "@Windows@HwndMSWheel$qqrruit1t1rit4",
58
+ "__fastcall Windows::HwndMSWheel(unsigned int&, unsigned int&, unsigned int&, int&, int&)"
59
+
60
+ # IDA uses '__int64' instead of 'long long'
61
+ check "@Sysutils@TryStrToInt64$qqrx17System@AnsiStringrj",
62
+ "__fastcall Sysutils::TryStrToInt64(const System::AnsiString, long long&)"
63
+
64
+ check "@Sysutils@Supports$qqrpx14System@TObjectrx5_GUIDpv",
65
+ "__fastcall Sysutils::Supports(System::TObject *, _GUID&, void *)"
66
+
67
+ check "@std@%vector$51boost@archive@detail@basic_iarchive_impl@cobject_id69std@%allocator$51boost@archive@detail@basic_iarchive_impl@cobject_id%%@$bsubs$qui",
68
+ "std::vector<boost::archive::detail::basic_iarchive_impl::cobject_id, std::allocator<boost::archive::detail::basic_iarchive_impl::cobject_id> >::operator [](unsigned int)"
69
+
70
+ check "@Dbcommon@GetTableNameFromSQLEx$qqrx17System@WideString25Dbcommon@IDENTIFIEROption",
71
+ "__fastcall Dbcommon::GetTableNameFromSQLEx(const System::WideString, Dbcommon::IDENTIFIEROption)"
72
+
73
+ end
@@ -0,0 +1,14 @@
1
+ $: << File.expand_path("../lib", File.dirname(__FILE__))
2
+ require 'unmangler'
3
+
4
+ RSpec.configure do |config|
5
+ config.treat_symbols_as_metadata_keys_with_true_values = true
6
+ config.run_all_when_everything_filtered = true
7
+ #config.filter_run :focus
8
+
9
+ # Run specs in random order to surface order dependencies. If you find an
10
+ # order dependency and want to debug it, you can fix the order by providing
11
+ # the seed, which is printed after each run.
12
+ # --seed 1234
13
+ #config.order = 'random'
14
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'unmangler/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "unmangler"
8
+ gem.version = Unmangler::VERSION
9
+ gem.authors = ["Andrey \"Zed\" Zaikin"]
10
+ gem.email = ["zed.0xff@gmail.com"]
11
+ gem.description = %q{Unmangles mangled C++/Delphi names"}
12
+ gem.summary = gem.description + %q{, i.e. '@myclass@func$qil' => 'myclass::func(int, long)'}
13
+ gem.homepage = "http://zed.0xff.me"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unmangler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrey "Zed" Zaikin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Unmangles mangled C++/Delphi names"
14
+ email:
15
+ - zed.0xff@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - .rspec
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
25
+ - README.md.tpl
26
+ - Rakefile
27
+ - lib/unmangler.rb
28
+ - lib/unmangler/borland.rb
29
+ - lib/unmangler/string_ptr.rb
30
+ - lib/unmangler/version.rb
31
+ - spec/borland_spec.rb
32
+ - spec/spec_helper.rb
33
+ - unmangler.gemspec
34
+ homepage: http://zed.0xff.me
35
+ licenses: []
36
+ metadata: {}
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project:
53
+ rubygems_version: 2.0.3
54
+ signing_key:
55
+ specification_version: 4
56
+ summary: Unmangles mangled C++/Delphi names", i.e. '@myclass@func$qil' => 'myclass::func(int,
57
+ long)'
58
+ test_files:
59
+ - spec/borland_spec.rb
60
+ - spec/spec_helper.rb