pwn 0.5.1 → 0.5.2

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.
@@ -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?
@@ -84,13 +166,40 @@ module PWN
84
166
  puts hexdump
85
167
  end
86
168
 
87
- binary_data = hexdump.lines.map do |line|
88
- line.split[1..8].map do |hex|
89
- [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
90
199
  end.join
91
- end.join
92
200
 
93
- File.binwrite(file, binary_data)
201
+ File.binwrite(file, binary_data)
202
+ end
94
203
  rescue StandardError => e
95
204
  raise e
96
205
  end
@@ -112,9 +221,61 @@ module PWN
112
221
  hashed: 'optional - return hexdump as hash instead of string (default: false)'
113
222
  )
114
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
+
115
275
  #{self}.reverse_dump(
116
276
  hexdump: 'required - hexdump returned from #dump method',
117
- 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'
118
279
  )
119
280
 
120
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.1'
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.1
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