pwn 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -58,15 +58,97 @@ module PWN
58
58
  raise e
59
59
  end
60
60
 
61
+ # Supported Method Parameters::
62
+ # hexdump = PWN::Plugins::XXD.fill_range_w_byte(
63
+ # hexdump: 'required - hexdump returned from #dump method',
64
+ # start_addr: 'required - start address to fill with byte',
65
+ # end_addr: 'required - end address to fill with byte',
66
+ # byte: 'required - byte to fill range with'
67
+ # )
68
+
69
+ def self.fill_range_w_byte(opts = {})
70
+ hexdump = opts[:hexdump]
71
+ start_addr = opts[:start_addr]
72
+ end_addr = opts[:end_addr]
73
+ byte = opts[:byte]
74
+
75
+ start_int = start_addr.to_i(16)
76
+ end_int = end_addr.to_i(16)
77
+
78
+ hexdump.each do |key, value|
79
+ key_int = key.to_i(16)
80
+ value[:hex] = Array.new(16, byte) if key_int >= start_int && key_int <= end_int
81
+ end
82
+
83
+ hexdump
84
+ end
85
+
86
+ # Supported Method Parameters::
87
+ # hex_offset = PWN::Plugins::XXD.calc_addr_offset(
88
+ # start_addr: 'required - start address to evaluate',
89
+ # target_addr: 'required - memory address to set breakpoint'
90
+ # )
91
+ # ^^^ Instructions for #{self}.calc_addr_offset:
92
+ # This is useful for calculating address offsets of known functions in debuggers
93
+ # to set breakpoints of instructions that are not known at runtime.
94
+ # 1. Set a breakpoint at main and record its address - this is the start_addr.
95
+ # For example in r2:
96
+ # ```
97
+ # [0x00001050]> db main
98
+ # [0x00001050]> ood
99
+ # [0x7fd16122b360]> dc
100
+ # INFO: hit breakpoint at: 0x562e8547d139
101
+ # [0x562e8547d139]> db
102
+ # ```
103
+ # 2. Populate start_addr w/ address (i.e. '0x562e8547d139') of a known function (e.g. main)
104
+ # 3. Step down to the instruction you want to set a breakpoint. Record its address...
105
+ # this is the target_addr.
106
+ # ```
107
+ # [0x562e8547d139]> v
108
+ # <step through to target instruction via F7/F8>
109
+ # ```
110
+ # 4. Get the hex offset value by calling this method
111
+ # 5. Future breakpoints can be calculated by adding the hex offset to the
112
+ # updated start_addr (which changes every time the binary is executed).
113
+ # If the offset returned is `0x00000ec2` a breakpoint in r2 can be set via:
114
+ # ```
115
+ # [0x00001050]> ood
116
+ # INFO: hit breakpoint at: 0x55ee0a0e5139
117
+ # [0x7f1a45bea360]> db main
118
+ # [0x7f1a45bea360]> db (main)+0x00000ec2
119
+ # [0x7f1a45bea360]> db
120
+ # 0x558eebd75139 - 0x558eebd7513a 1 --x sw break enabled valid ...
121
+ # 0x558eebd75ffb - 0x558eebd75ffc 1 --x sw break enabled valid ...
122
+ # [0x55ee0a0e5139]> dc
123
+ # [0x7feddfd2d360]> dc
124
+ # INFO: hit breakpoint at: 0x558eebd75139
125
+ # INFO: hit breakpoint at: 0x5558c3101ffb
126
+ # [0x5558c3101ffb]> v
127
+ # <step through via F7, F8, F9, etc. to get to desired breakpoint>
128
+ # ```
129
+
130
+ def self.calc_addr_offset(opts = {})
131
+ start_addr = opts[:start_addr]
132
+ target_addr = opts[:target_addr]
133
+
134
+ format(
135
+ '0x%<s1>08x',
136
+ s1: target_addr.to_i(16) - start_addr.to_i(16)
137
+ )
138
+ end
139
+
61
140
  # Supported Method Parameters::
62
141
  # PWN::Plugins::XXD.reverse_dump(
63
142
  # hexdump: 'required - hexdump returned from #dump method',
64
- # file: 'required - path to binary file to dump'
143
+ # file: 'required - path to binary file to dump',
144
+ # byte_chunks: 'optional - if set, will write n byte chunks of hexdump to multiple files'
65
145
  # )
66
146
 
67
147
  def self.reverse_dump(opts = {})
68
148
  hexdump = opts[:hexdump]
69
149
  file = opts[:file]
150
+ byte_chunks = opts[:byte_chunks].to_i
151
+
70
152
  raise ArgumentError, 'hexdump is required' if hexdump.nil?
71
153
 
72
154
  raise ArgumentError, 'output file is required' if file.nil?
@@ -81,17 +163,43 @@ module PWN
81
163
  s3: v[:ascii]
82
164
  )
83
165
  end.join
84
- puts k
85
166
  puts hexdump
86
167
  end
87
168
 
88
- binary_data = hexdump.lines.map do |line|
89
- line.split[1..8].map do |hex|
90
- [hex].pack('H*')
169
+ # Useful for testing which chunk(s)
170
+ # trigger malware detection engines
171
+ if byte_chunks.to_i.positive?
172
+ # Raise error if byte_chunks is not divisible by 16
173
+ raise ArgumentError, 'byte_chunks must be divisible by 16' if (byte_chunks % 16).positive?
174
+
175
+ # Raise error if byte_chunks is greater than hexdump size
176
+ raise ArgumentError, 'byte_chunks must be less than hexdump size' if byte_chunks > hexdump.size
177
+
178
+ chunks = byte_chunks / 16
179
+ hexdump.lines.each_slice(chunks) do |chunk|
180
+ # File name should append memory address of chunks
181
+ # to make analysis possible
182
+ start_chunk_addr = chunk.first[0..7]
183
+ end_chunk_addr = chunk.last[0..7]
184
+ chunk_file = "#{file}.#{start_chunk_addr}-#{end_chunk_addr}"
185
+
186
+ binary_data = chunk.map do |line|
187
+ line.split[1..8].map do |hex|
188
+ [hex].pack('H*')
189
+ end.join
190
+ end.join
191
+
192
+ File.binwrite(chunk_file, binary_data)
193
+ end
194
+ else
195
+ binary_data = hexdump.lines.map do |line|
196
+ line.split[1..8].map do |hex|
197
+ [hex].pack('H*')
198
+ end.join
91
199
  end.join
92
- end.join
93
200
 
94
- File.binwrite(file, binary_data)
201
+ File.binwrite(file, binary_data)
202
+ end
95
203
  rescue StandardError => e
96
204
  raise e
97
205
  end
@@ -113,9 +221,61 @@ module PWN
113
221
  hashed: 'optional - return hexdump as hash instead of string (default: false)'
114
222
  )
115
223
 
224
+ hexdump = #{self}.fill_range_w_byte(
225
+ hexdump: 'required - hexdump returned from #dump method',
226
+ start_addr: 'required - start address to fill with byte',
227
+ end_addr: 'required - end address to fill with byte',
228
+ byte: 'required - byte to fill range with'
229
+ )
230
+
231
+ hex_offset = #{self}.calc_addr_offset(
232
+ start_addr: 'required - start address to evaluate',
233
+ target_addr: 'required - memory address to set breakpoint'
234
+ )
235
+
236
+ # ^^^ Instructions for #{self}.calc_addr_offset:
237
+ # This is useful for calculating address offsets of known functions in debuggers
238
+ # to set breakpoints of instructions that are not known at runtime.
239
+ # 1. Set a breakpoint at main and record its address - this is the start_addr.
240
+ # For example in r2:
241
+ # ```
242
+ # [0x00001050]> db main
243
+ # [0x00001050]> ood
244
+ # [0x7fd16122b360]> dc
245
+ # INFO: hit breakpoint at: 0x562e8547d139
246
+ # [0x562e8547d139]> db
247
+ # ```
248
+ # 2. Populate start_addr w/ address (i.e. '0x562e8547d139') of a known function (e.g. main)
249
+ # 3. Step down to the instruction you want to set a breakpoint. Record its address...
250
+ # this is the target_addr.
251
+ # ```
252
+ # [0x562e8547d139]> v
253
+ # <step through to target instruction via F7/F8>
254
+ # ```
255
+ # 4. Get the hex offset value by calling this method
256
+ # 5. Future breakpoints can be calculated by adding the hex offset to the
257
+ # updated start_addr (which changes every time the binary is executed).
258
+ # If the offset returned is `0x00000ec2` a breakpoint in r2 can be set via:
259
+ # ```
260
+ # [0x00001050]> ood
261
+ # INFO: hit breakpoint at: 0x55ee0a0e5139
262
+ # [0x7f1a45bea360]> db main
263
+ # [0x7f1a45bea360]> db (main)+0x00000ec2
264
+ # [0x7f1a45bea360]> db
265
+ # 0x558eebd75139 - 0x558eebd7513a 1 --x sw break enabled valid ...
266
+ # 0x558eebd75ffb - 0x558eebd75ffc 1 --x sw break enabled valid ...
267
+ # [0x55ee0a0e5139]> dc
268
+ # [0x7feddfd2d360]> dc
269
+ # INFO: hit breakpoint at: 0x558eebd75139
270
+ # INFO: hit breakpoint at: 0x5558c3101ffb
271
+ # [0x5558c3101ffb]> v
272
+ # <step through via F7, F8, F9, etc. to get to desired breakpoint>
273
+ # ```
274
+
116
275
  #{self}.reverse_dump(
117
276
  hexdump: 'required - hexdump returned from #dump method',
118
- file: 'required - path to binary file to dump'
277
+ file: 'required - path to binary file to dump',
278
+ byte_chunks: 'optional - if set, will write n byte chunks of hexdump to multiple files'
119
279
  )
120
280
 
121
281
  #{self}.authors
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.0'
4
+ VERSION = '0.5.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-25 00:00:00.000000000 Z
11
+ date: 2024-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport