one_gadget 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc7692c2d1de780ad214a4c259f42a06560c664c9ec9e6db55e01ca5856c3a3b
4
- data.tar.gz: ad1d2b9efcc87b69e07e02e3d0a7826174f73b46217e459eeedab881d6d43bf7
3
+ metadata.gz: 115a1008facd6ff265526eb0be8392bca7cd4eab161b549ead9ab6f34a0050b2
4
+ data.tar.gz: 56f21220b1a65fe15ac51b682f95ba52fb108084912570f8208f1ef40eafda52
5
5
  SHA512:
6
- metadata.gz: 7ae80fea1083e6c72672d7b05fc5dbb769c3a53e2974f56f4e8162726dfdf811d677d746ef573c7310fefb382af9eef18a306cdc5431a7c8c1bc877ac4f30f74
7
- data.tar.gz: 6deec0fe4bf09d84ff8e8b93bbdecea02ab69861115222a176b8ff4406163ba1255cdf874d50e9d4d2f3d1707a89f831c8c010f9cd7b73ca89134a87c6cc336a
6
+ metadata.gz: 5c5714e03eda9a982d9d1510ad5f0465e3f11e55155507910df4302e039d92a3a5c35cf5be45c0a8f30709b491fcb301d00e8e9d57638610c1e0042282e87a02
7
+ data.tar.gz: 21ac5b3a5cc316c92e90741bcec4e5efbdc8d97183c3810eba356216c636a9d4d59c3a62784e2395731d72a3c716fa8c10eec8697f04437e3da2a1c41a292c0c
data/README.md CHANGED
@@ -64,18 +64,20 @@ $ one_gadget
64
64
 
65
65
  ```bash
66
66
  $ one_gadget /lib/x86_64-linux-gnu/libc.so.6
67
- # 0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
67
+ # 0xe3afe execve("/bin/sh", r15, r12)
68
68
  # constraints:
69
- # rsp & 0xf == 0
70
- # rcx == NULL
69
+ # [r15] == NULL || r15 == NULL || r15 is a valid argv
70
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
71
71
  #
72
- # 0x4f322 execve("/bin/sh", rsp+0x40, environ)
72
+ # 0xe3b01 execve("/bin/sh", r15, rdx)
73
73
  # constraints:
74
- # [rsp+0x40] == NULL
74
+ # [r15] == NULL || r15 == NULL || r15 is a valid argv
75
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
75
76
  #
76
- # 0x10a38c execve("/bin/sh", rsp+0x70, environ)
77
+ # 0xe3b04 execve("/bin/sh", rsi, rdx)
77
78
  # constraints:
78
- # [rsp+0x70] == NULL
79
+ # [rsi] == NULL || rsi == NULL || rsi is a valid argv
80
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
79
81
 
80
82
  ```
81
83
  ![x86_64](https://github.com/david942j/one_gadget/blob/master/examples/x86_64.png?raw=true)
@@ -83,21 +85,17 @@ $ one_gadget /lib/x86_64-linux-gnu/libc.so.6
83
85
  #### Given BuildID
84
86
  ```bash
85
87
  $ one_gadget -b aad7dbe330f23ea00ca63daf793b766b51aceb5d
86
- # 0x45526 execve("/bin/sh", rsp+0x30, environ)
87
- # constraints:
88
- # rax == NULL
89
- #
90
88
  # 0x4557a execve("/bin/sh", rsp+0x30, environ)
91
89
  # constraints:
92
- # [rsp+0x30] == NULL
90
+ # [rsp+0x30] == NULL || {[rsp+0x30], [rsp+0x38], [rsp+0x40], [rsp+0x48], ...} is a valid argv
93
91
  #
94
92
  # 0xf1651 execve("/bin/sh", rsp+0x40, environ)
95
93
  # constraints:
96
- # [rsp+0x40] == NULL
94
+ # [rsp+0x40] == NULL || {[rsp+0x40], [rsp+0x48], [rsp+0x50], [rsp+0x58], ...} is a valid argv
97
95
  #
98
96
  # 0xf24cb execve("/bin/sh", rsp+0x60, environ)
99
97
  # constraints:
100
- # [rsp+0x60] == NULL
98
+ # [rsp+0x60] == NULL || {[rsp+0x60], [rsp+0x68], [rsp+0x70], [rsp+0x78], ...} is a valid argv
101
99
 
102
100
  ```
103
101
  ![build id](https://github.com/david942j/one_gadget/blob/master/examples/from_build_id.png?raw=true)
@@ -120,33 +118,37 @@ Reorder gadgets according to the distance of given functions.
120
118
 
121
119
  ```bash
122
120
  $ one_gadget /lib/x86_64-linux-gnu/libc.so.6 --near exit,mkdir
123
- # [OneGadget] Gadgets near exit(0x43120):
124
- # 0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
121
+ # [OneGadget] Gadgets near exit(0x46a40):
122
+ # 0xe3afe execve("/bin/sh", r15, r12)
125
123
  # constraints:
126
- # rsp & 0xf == 0
127
- # rcx == NULL
124
+ # [r15] == NULL || r15 == NULL || r15 is a valid argv
125
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
128
126
  #
129
- # 0x4f322 execve("/bin/sh", rsp+0x40, environ)
127
+ # 0xe3b01 execve("/bin/sh", r15, rdx)
130
128
  # constraints:
131
- # [rsp+0x40] == NULL
129
+ # [r15] == NULL || r15 == NULL || r15 is a valid argv
130
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
132
131
  #
133
- # 0x10a38c execve("/bin/sh", rsp+0x70, environ)
132
+ # 0xe3b04 execve("/bin/sh", rsi, rdx)
134
133
  # constraints:
135
- # [rsp+0x70] == NULL
134
+ # [rsi] == NULL || rsi == NULL || rsi is a valid argv
135
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
136
136
  #
137
- # [OneGadget] Gadgets near mkdir(0x10fbb0):
138
- # 0x10a38c execve("/bin/sh", rsp+0x70, environ)
137
+ # [OneGadget] Gadgets near mkdir(0x10de70):
138
+ # 0xe3b04 execve("/bin/sh", rsi, rdx)
139
139
  # constraints:
140
- # [rsp+0x70] == NULL
140
+ # [rsi] == NULL || rsi == NULL || rsi is a valid argv
141
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
141
142
  #
142
- # 0x4f322 execve("/bin/sh", rsp+0x40, environ)
143
+ # 0xe3b01 execve("/bin/sh", r15, rdx)
143
144
  # constraints:
144
- # [rsp+0x40] == NULL
145
+ # [r15] == NULL || r15 == NULL || r15 is a valid argv
146
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
145
147
  #
146
- # 0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
148
+ # 0xe3afe execve("/bin/sh", r15, r12)
147
149
  # constraints:
148
- # rsp & 0xf == 0
149
- # rcx == NULL
150
+ # [r15] == NULL || r15 == NULL || r15 is a valid argv
151
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
150
152
  #
151
153
 
152
154
  ```
@@ -155,11 +157,11 @@ $ one_gadget /lib/x86_64-linux-gnu/libc.so.6 --near exit,mkdir
155
157
  Regular expression is acceptable.
156
158
  ```bash
157
159
  $ one_gadget /lib/x86_64-linux-gnu/libc.so.6 --near 'write.*' --raw
158
- # [OneGadget] Gadgets near writev(0x1166a0):
159
- # 1090444 324386 324293
160
+ # [OneGadget] Gadgets near writev(0x114690):
161
+ # 932612 932609 932606
160
162
  #
161
- # [OneGadget] Gadgets near write(0x110140):
162
- # 1090444 324386 324293
163
+ # [OneGadget] Gadgets near write(0x10e280):
164
+ # 932612 932609 932606
163
165
  #
164
166
 
165
167
  ```
@@ -167,23 +169,23 @@ $ one_gadget /lib/x86_64-linux-gnu/libc.so.6 --near 'write.*' --raw
167
169
  Pass an ELF file as the argument, OneGadget will take all GOT functions for processing.
168
170
  ```bash
169
171
  $ one_gadget /lib/x86_64-linux-gnu/libc.so.6 --near spec/data/test_near_file.elf --raw
170
- # [OneGadget] Gadgets near exit(0x43120):
171
- # 324293 324386 1090444
172
+ # [OneGadget] Gadgets near exit(0x46a40):
173
+ # 932606 932609 932612
172
174
  #
173
- # [OneGadget] Gadgets near puts(0x809c0):
174
- # 324386 324293 1090444
175
+ # [OneGadget] Gadgets near puts(0x84420):
176
+ # 932606 932609 932612
175
177
  #
176
- # [OneGadget] Gadgets near printf(0x64e80):
177
- # 324386 324293 1090444
178
+ # [OneGadget] Gadgets near printf(0x61c90):
179
+ # 932606 932609 932612
178
180
  #
179
- # [OneGadget] Gadgets near strlen(0x9dc70):
180
- # 324386 324293 1090444
181
+ # [OneGadget] Gadgets near strlen(0x9f630):
182
+ # 932606 932609 932612
181
183
  #
182
- # [OneGadget] Gadgets near __cxa_finalize(0x43520):
183
- # 324293 324386 1090444
184
+ # [OneGadget] Gadgets near __cxa_finalize(0x46f10):
185
+ # 932606 932609 932612
184
186
  #
185
- # [OneGadget] Gadgets near __libc_start_main(0x21ab0):
186
- # 324293 324386 1090444
187
+ # [OneGadget] Gadgets near __libc_start_main(0x23f90):
188
+ # 932606 932609 932612
187
189
  #
188
190
 
189
191
  ```
@@ -197,89 +199,286 @@ Use option `--level 1` to show all gadgets found instead of only those with high
197
199
 
198
200
  ```bash
199
201
  $ one_gadget /lib/x86_64-linux-gnu/libc.so.6 --level 1
200
- # 0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
202
+ # 0x51dfb posix_spawn(rsp+0xc, "/bin/sh", 0, rbp, rsp+0x50, environ)
201
203
  # constraints:
204
+ # address rsp+0x60 is writable
202
205
  # rsp & 0xf == 0
203
- # rcx == NULL
206
+ # {"sh", "-c", rbx, NULL} is a valid argv
207
+ # rbp == NULL || (u16)[rbp] == NULL
204
208
  #
205
- # 0x4f322 execve("/bin/sh", rsp+0x40, environ)
209
+ # 0x51e02 posix_spawn(rsp+0xc, "/bin/sh", 0, rbp, rsp+0x50, environ)
206
210
  # constraints:
207
- # [rsp+0x40] == NULL
211
+ # address rsp+0x60 is writable
212
+ # rsp & 0xf == 0
213
+ # rax == NULL || {"sh", rax, rbx, NULL} is a valid argv
214
+ # rbp == NULL || (u16)[rbp] == NULL
208
215
  #
209
- # 0xe569f execve("/bin/sh", r14, r12)
216
+ # 0x51e09 posix_spawn(rsp+0xc, "/bin/sh", 0, rbp, rsp+0x50, environ)
210
217
  # constraints:
211
- # [r14] == NULL || r14 == NULL
212
- # [r12] == NULL || r12 == NULL
218
+ # address rsp+0x60 is writable
219
+ # rsp & 0xf == 0
220
+ # rcx == NULL || {rcx, rax, rbx, NULL} is a valid argv
221
+ # rbp == NULL || (u16)[rbp] == NULL
213
222
  #
214
- # 0xe5858 execve("/bin/sh", [rbp-0x88], [rbp-0x70])
223
+ # 0x51e10 posix_spawn(rsp+0xc, "/bin/sh", rdx, rbp, rsp+0x50, environ)
215
224
  # constraints:
216
- # [[rbp-0x88]] == NULL || [rbp-0x88] == NULL
217
- # [[rbp-0x70]] == NULL || [rbp-0x70] == NULL
225
+ # address rsp+0x60 is writable
226
+ # rsp & 0xf == 0
227
+ # rcx == NULL || {rcx, (u64)xmm1, rbx, NULL} is a valid argv
228
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
229
+ # rbp == NULL || (u16)[rbp] == NULL
218
230
  #
219
- # 0xe585f execve("/bin/sh", r10, [rbp-0x70])
231
+ # 0x51e15 posix_spawn(rsp+0xc, "/bin/sh", rdx, rbp, rsp+0x50, environ)
220
232
  # constraints:
221
- # [r10] == NULL || r10 == NULL
222
- # [[rbp-0x70]] == NULL || [rbp-0x70] == NULL
233
+ # address rsp+0x60 is writable
234
+ # rsp & 0xf == 0
235
+ # (u64)xmm0 == NULL || {(u64)xmm0, (u64)xmm1, rbx, NULL} is a valid argv
236
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
237
+ # rbp == NULL || (u16)[rbp] == NULL
223
238
  #
224
- # 0xe5863 execve("/bin/sh", r10, rdx)
239
+ # 0x51e25 posix_spawn(rdi, "/bin/sh", rdx, rbp, rsp+0x50, [rax])
225
240
  # constraints:
226
- # [r10] == NULL || r10 == NULL
227
- # [rdx] == NULL || rdx == NULL
241
+ # address rsp+0x60 is writable
242
+ # rsp & 0xf == 0
243
+ # (u64)xmm0 == NULL || {(u64)xmm0, (u64)(xmm0 >> 64), rbx, NULL} is a valid argv
244
+ # [[rax]] == NULL || [rax] == NULL || [rax] is a valid envp
245
+ # rdi == NULL || writable: rdi
246
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
247
+ # rbp == NULL || (u16)[rbp] == NULL
228
248
  #
229
- # 0x10a38c execve("/bin/sh", rsp+0x70, environ)
249
+ # 0x51e2a posix_spawn(rdi, "/bin/sh", rdx, rbp, r8, [rax])
230
250
  # constraints:
231
- # [rsp+0x70] == NULL
251
+ # address rsp+0x60 is writable
252
+ # rsp & 0xf == 0
253
+ # [r8] == NULL || r8 is a valid argv
254
+ # [[rax]] == NULL || [rax] == NULL || [rax] is a valid envp
255
+ # rdi == NULL || writable: rdi
256
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
257
+ # rbp == NULL || (u16)[rbp] == NULL
232
258
  #
233
- # 0x10a398 execve("/bin/sh", rsi, [rax])
259
+ # 0x51e2d posix_spawn(rdi, "/bin/sh", rdx, rcx, r8, [rax])
234
260
  # constraints:
235
- # [rsi] == NULL || rsi == NULL
236
- # [[rax]] == NULL || [rax] == NULL
237
-
238
- ```
239
-
240
- #### Other Architectures
241
-
242
- ##### i386
243
- ```bash
244
- $ one_gadget /lib32/libc.so.6
245
- # 0x3cbea execve("/bin/sh", esp+0x34, environ)
261
+ # address rsp+0x60 is writable
262
+ # rsp & 0xf == 0
263
+ # [r8] == NULL || r8 is a valid argv
264
+ # [[rax]] == NULL || [rax] == NULL || [rax] is a valid envp
265
+ # rdi == NULL || writable: rdi
266
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
267
+ # rcx == NULL || (u16)[rcx] == NULL
268
+ #
269
+ # 0x51e32 posix_spawn(rdi, "/bin/sh", rdx, rcx, r8, [rax])
246
270
  # constraints:
247
- # esi is the GOT address of libc
248
- # [esp+0x34] == NULL
271
+ # address rsp+0x68 is writable
272
+ # rsp & 0xf == 0
273
+ # [r8] == NULL || r8 is a valid argv
274
+ # [[rax]] == NULL || [rax] == NULL || [rax] is a valid envp
275
+ # rdi == NULL || writable: rdi
276
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
277
+ # rcx == NULL || (u16)[rcx] == NULL
249
278
  #
250
- # 0x3cbec execve("/bin/sh", esp+0x38, environ)
279
+ # 0x84135 posix_spawn(rbx+0xe0, "/bin/sh", r12, 0, rsp+0x60, environ)
251
280
  # constraints:
252
- # esi is the GOT address of libc
253
- # [esp+0x38] == NULL
281
+ # address rsp+0x70 is writable
282
+ # rsp & 0xf == 0
283
+ # {"sh", "-c", rbp, NULL} is a valid argv
284
+ # rbx+0xe0 == NULL || writable: rbx+0xe0
285
+ # r12 == NULL || (s32)[r12+0x4] <= 0
254
286
  #
255
- # 0x3cbf0 execve("/bin/sh", esp+0x3c, environ)
287
+ # 0x8413c posix_spawn(rbx+0xe0, "/bin/sh", r12, 0, rsp+0x60, environ)
256
288
  # constraints:
257
- # esi is the GOT address of libc
258
- # [esp+0x3c] == NULL
289
+ # address rsp+0x70 is writable
290
+ # rsp & 0xf == 0
291
+ # rax == NULL || {"sh", rax, rbp, NULL} is a valid argv
292
+ # rbx+0xe0 == NULL || writable: rbx+0xe0
293
+ # r12 == NULL || (s32)[r12+0x4] <= 0
259
294
  #
260
- # 0x3cbf7 execve("/bin/sh", esp+0x40, environ)
295
+ # 0x84143 posix_spawn(rbx+0xe0, "/bin/sh", r12, 0, rsp+0x60, environ)
261
296
  # constraints:
262
- # esi is the GOT address of libc
263
- # [esp+0x40] == NULL
297
+ # address rsp+0x70 is writable
298
+ # rsp & 0xf == 0
299
+ # rcx == NULL || {rcx, rax, rbp, NULL} is a valid argv
300
+ # rbx+0xe0 == NULL || writable: rbx+0xe0
301
+ # r12 == NULL || (s32)[r12+0x4] <= 0
264
302
  #
265
- # 0x6729f execl("/bin/sh", eax)
303
+ # 0x84146 posix_spawn(rbx+0xe0, "/bin/sh", rdx, 0, rsp+0x60, environ)
266
304
  # constraints:
267
- # esi is the GOT address of libc
268
- # eax == NULL
305
+ # address rsp+0x70 is writable
306
+ # rsp & 0xf == 0
307
+ # rcx == NULL || {rcx, rax, rbp, NULL} is a valid argv
308
+ # rbx+0xe0 == NULL || writable: rbx+0xe0
309
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
269
310
  #
270
- # 0x672a0 execl("/bin/sh", [esp])
311
+ # 0x8414b posix_spawn(rbx+0xe0, "/bin/sh", rdx, 0, rsp+0x60, environ)
271
312
  # constraints:
272
- # esi is the GOT address of libc
273
- # [esp] == NULL
313
+ # address rsp+0x78 is writable
314
+ # rsp & 0xf == 0
315
+ # rcx == NULL || {rcx, rax, [rsp+0x70], NULL} is a valid argv
316
+ # rbx+0xe0 == NULL || writable: rbx+0xe0
317
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
318
+ #
319
+ # 0x84150 posix_spawn(rbx+0xe0, "/bin/sh", rdx, 0, rsp+0x60, environ)
320
+ # constraints:
321
+ # address rsp+0x78 is writable
322
+ # rsp & 0xf == 0
323
+ # rcx == NULL || {rcx, (u64)xmm1, [rsp+0x70], NULL} is a valid argv
324
+ # rbx+0xe0 == NULL || writable: rbx+0xe0
325
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
326
+ #
327
+ # 0x8415c posix_spawn(rbx+0xe0, "/bin/sh", rdx, 0, rsp+0x60, [rax])
328
+ # constraints:
329
+ # address rsp+0x78 is writable
330
+ # rsp & 0xf == 0
331
+ # (u64)xmm0 == NULL || {(u64)xmm0, (u64)xmm1, [rsp+0x70], NULL} is a valid argv
332
+ # [[rax]] == NULL || [rax] == NULL || [rax] is a valid envp
333
+ # rbx+0xe0 == NULL || writable: rbx+0xe0
334
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
335
+ #
336
+ # 0x84162 posix_spawn(rbx+0xe0, "/bin/sh", rdx, rcx, rsp+0x60, [rax])
337
+ # constraints:
338
+ # address rsp+0x78 is writable
339
+ # rsp & 0xf == 0
340
+ # (u64)xmm0 == NULL || {(u64)xmm0, (u64)(xmm0 >> 64), [rsp+0x70], NULL} is a valid argv
341
+ # [[rax]] == NULL || [rax] == NULL || [rax] is a valid envp
342
+ # rbx+0xe0 == NULL || writable: rbx+0xe0
343
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
344
+ # rcx == NULL || (u16)[rcx] == NULL
345
+ #
346
+ # 0x84169 posix_spawn(rdi, "/bin/sh", rdx, rcx, rsp+0x60, [rax])
347
+ # constraints:
348
+ # address rsp+0x78 is writable
349
+ # rsp & 0xf == 0
350
+ # (u64)xmm0 == NULL || {(u64)xmm0, (u64)(xmm0 >> 64), [rsp+0x70], NULL} is a valid argv
351
+ # [[rax]] == NULL || [rax] == NULL || [rax] is a valid envp
352
+ # rdi == NULL || writable: rdi
353
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
354
+ # rcx == NULL || (u16)[rcx] == NULL
355
+ #
356
+ # 0x84170 posix_spawn(rdi, "/bin/sh", rdx, rcx, r8, [rax])
357
+ # constraints:
358
+ # address rsp+0x78 is writable
359
+ # rsp & 0xf == 0
360
+ # [r8] == NULL || r8 is a valid argv
361
+ # [[rax]] == NULL || [rax] == NULL || [rax] is a valid envp
362
+ # rdi == NULL || writable: rdi
363
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
364
+ # rcx == NULL || (u16)[rcx] == NULL
365
+ #
366
+ # 0xe3afe execve("/bin/sh", r15, r12)
367
+ # constraints:
368
+ # [r15] == NULL || r15 == NULL || r15 is a valid argv
369
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
370
+ #
371
+ # 0xe3b01 execve("/bin/sh", r15, rdx)
372
+ # constraints:
373
+ # [r15] == NULL || r15 == NULL || r15 is a valid argv
374
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
375
+ #
376
+ # 0xe3b04 execve("/bin/sh", rsi, rdx)
377
+ # constraints:
378
+ # [rsi] == NULL || rsi == NULL || rsi is a valid argv
379
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
380
+ #
381
+ # 0xe3cf3 execve("/bin/sh", r10, r12)
382
+ # constraints:
383
+ # address rbp-0x78 is writable
384
+ # [r10] == NULL || r10 == NULL || r10 is a valid argv
385
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
386
+ #
387
+ # 0xe3cf6 execve("/bin/sh", r10, rdx)
388
+ # constraints:
389
+ # address rbp-0x78 is writable
390
+ # [r10] == NULL || r10 == NULL || r10 is a valid argv
391
+ # [rdx] == NULL || rdx == NULL || rdx is a valid envp
274
392
  #
275
- # 0x13573e execl("/bin/sh", eax)
393
+ # 0xe3d62 execve("/bin/sh", rbp-0x50, r12)
276
394
  # constraints:
395
+ # address rbp-0x48 is writable
396
+ # r13 == NULL || {"/bin/sh", r13, NULL} is a valid argv
397
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
398
+ #
399
+ # 0xe3d69 execve("/bin/sh", rbp-0x50, r12)
400
+ # constraints:
401
+ # address rbp-0x48 is writable
402
+ # rax == NULL || {rax, r13, NULL} is a valid argv
403
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
404
+ #
405
+ # 0xe3d70 execve("/bin/sh", rbp-0x50, r12)
406
+ # constraints:
407
+ # address rbp-0x50 is writable
408
+ # rax == NULL || {rax, [rbp-0x48], NULL} is a valid argv
409
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
410
+ #
411
+ # 0xe3da7 execve("/bin/sh", rbp-0x50, r12)
412
+ # constraints:
413
+ # address rbp-0x50 is writable
414
+ # [rbp-0x68] == NULL || {"/bin/sh", [rbp-0x68], NULL} is a valid argv
415
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
416
+ #
417
+ # 0xe3db1 execve("/bin/sh", rbp-0x50, r12)
418
+ # constraints:
419
+ # address rbp-0x50 is writable
420
+ # rax == NULL || {rax, [rbp-0x68], NULL} is a valid argv
421
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
422
+ #
423
+ # 0xe3db5 execve("/bin/sh", r10, r12)
424
+ # constraints:
425
+ # addresses r10+0x10, rbp-0x50 are writable
426
+ # [r10] == NULL || r10 == NULL || r10 is a valid argv
427
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
428
+ #
429
+ # 0xe3dbd execve("/bin/sh", r10, r12)
430
+ # constraints:
431
+ # addresses r10+0x10, rbp-0x48 are writable
432
+ # [r10] == NULL || r10 == NULL || r10 is a valid argv
433
+ # [r12] == NULL || r12 == NULL || r12 is a valid envp
434
+ #
435
+ # 0x1077ca posix_spawn(rsp+0x64, "/bin/sh", [rsp+0x38], 0, rsp+0x70, [rsp+0xf0])
436
+ # constraints:
437
+ # [rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv
438
+ # [[rsp+0xf0]] == NULL || [rsp+0xf0] == NULL || [rsp+0xf0] is a valid envp
439
+ # [rsp+0x38] == NULL || (s32)[[rsp+0x38]+0x4] <= 0
440
+ #
441
+ # 0x1077d2 posix_spawn(rsp+0x64, "/bin/sh", [rsp+0x38], 0, rsp+0x70, r9)
442
+ # constraints:
443
+ # [rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv
444
+ # [r9] == NULL || r9 == NULL || r9 is a valid envp
445
+ # [rsp+0x38] == NULL || (s32)[[rsp+0x38]+0x4] <= 0
446
+ #
447
+ # 0x1077d7 posix_spawn(rsp+0x64, "/bin/sh", rdx, 0, rsp+0x70, r9)
448
+ # constraints:
449
+ # [rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv
450
+ # [r9] == NULL || r9 == NULL || r9 is a valid envp
451
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
452
+ #
453
+ # 0x1077e1 posix_spawn(rdi, "/bin/sh", rdx, 0, r8, r9)
454
+ # constraints:
455
+ # [r8] == NULL || r8 is a valid argv
456
+ # [r9] == NULL || r9 == NULL || r9 is a valid envp
457
+ # rdi == NULL || writable: rdi
458
+ # rdx == NULL || (s32)[rdx+0x4] <= 0
459
+
460
+ ```
461
+
462
+ #### Other Architectures
463
+
464
+ ##### i386
465
+ ```bash
466
+ $ one_gadget /lib32/libc.so.6
467
+ # 0xc890b execve("/bin/sh", [ebp-0x2c], esi)
468
+ # constraints:
469
+ # address ebp-0x20 is writable
277
470
  # ebx is the GOT address of libc
471
+ # [[ebp-0x2c]] == NULL || [ebp-0x2c] == NULL || [ebp-0x2c] is a valid argv
472
+ # [esi] == NULL || esi == NULL || esi is a valid envp
473
+ #
474
+ # 0x1421b3 execl("/bin/sh", eax)
475
+ # constraints:
476
+ # ebp is the GOT address of libc
278
477
  # eax == NULL
279
478
  #
280
- # 0x13573f execl("/bin/sh", [esp])
479
+ # 0x1421b4 execl("/bin/sh", [esp])
281
480
  # constraints:
282
- # ebx is the GOT address of libc
481
+ # ebp is the GOT address of libc
283
482
  # [esp] == NULL
284
483
 
285
484
  ```
@@ -324,15 +523,15 @@ $ one_gadget ./spec/data/libc-2.19.so -s 'echo "offset ->"'
324
523
  ```ruby
325
524
  require 'one_gadget'
326
525
  OneGadget.gadgets(file: '/lib/x86_64-linux-gnu/libc.so.6')
327
- #=> [324293, 324386, 1090444]
526
+ #=> [932606, 932609, 932612]
328
527
 
329
528
  # or in shorter way
330
529
  one_gadget('/lib/x86_64-linux-gnu/libc.so.6', level: 1)
331
- #=> [324293, 324386, 939679, 940120, 940127, 940131, 1090444, 1090456]
530
+ #=> [335355, 335362, 335369, 335376, 335381, 335397, 335402, 335405, 335410, 540981, 540988, 540995, 540998, 541003, 541008, 541020, 541026, 541033, 541040, 932606, 932609, 932612, 933107, 933110, 933218, 933225, 933232, 933287, 933297, 933301, 933309, 1079242, 1079250, 1079255, 1079265]
332
531
 
333
532
  # from build id
334
533
  one_gadget('b417c0ba7cc5cf06d1d1bed6652cedb9253c60d0')
335
- #=> [324293, 324386, 1090444]
534
+ #=> [324286, 324293, 324386, 1090444]
336
535
 
337
536
  ```
338
537
 
@@ -343,7 +542,7 @@ def one_gadget(filename):
343
542
  return [int(i) for i in subprocess.check_output(['one_gadget', '--raw', filename]).decode().split(' ')]
344
543
 
345
544
  one_gadget('/lib/x86_64-linux-gnu/libc.so.6')
346
- #=> [324293, 324386, 1090444]
545
+ #=> [932606, 932609, 932612]
347
546
 
348
547
  ```
349
548
 
@@ -12,7 +12,7 @@ module OneGadget
12
12
  # Help message.
13
13
  USAGE = 'Usage: one_gadget <FILE|-b BuildID> [options]'
14
14
  # Default options.
15
- DEFAULT_OPTIONS = { raw: false, force_file: false, level: 0, base: 0 }.freeze
15
+ DEFAULT_OPTIONS = { format: :pretty, force_file: false, level: 0, base: 0 }.freeze
16
16
 
17
17
  module_function
18
18
 
@@ -49,9 +49,9 @@ module OneGadget
49
49
  return show(parser.help) && false unless build_id || libc_file
50
50
 
51
51
  gadgets = if build_id
52
- OneGadget.gadgets(build_id: build_id, details: true, level: level)
52
+ OneGadget.gadgets(build_id:, details: true, level:)
53
53
  else # libc_file
54
- OneGadget.gadgets(file: libc_file, details: true, force_file: @options[:force_file], level: level)
54
+ OneGadget.gadgets(file: libc_file, details: true, force_file: @options[:force_file], level:)
55
55
  end
56
56
  gadgets.each { |g| g.base = @options[:base] }
57
57
  handle_gadgets(gadgets, libc_file)
@@ -66,7 +66,7 @@ module OneGadget
66
66
  return handle_script(gadgets, @options[:script]) if @options[:script]
67
67
  return handle_near(libc_file, gadgets, @options[:near]) if @options[:near]
68
68
 
69
- display_gadgets(gadgets, @options[:raw])
69
+ display_gadgets(gadgets, @options[:format])
70
70
  end
71
71
 
72
72
  # Displays libc information given BuildID.
@@ -119,13 +119,18 @@ module OneGadget
119
119
  @options[:level] = l
120
120
  end
121
121
 
122
- opts.on('-n', '--near FUNCTIONS/FILE', 'Order gadgets by their distance to the given functions'\
123
- ' or to the GOT functions of the given file.') do |n|
122
+ opts.on('-n', '--near FUNCTIONS/FILE', 'Order gadgets by their distance to the given functions ' \
123
+ 'or to the GOT functions of the given file.') do |n|
124
124
  @options[:near] = n
125
125
  end
126
126
 
127
- opts.on('-r', '--[no-]raw', 'Output gadgets offset only, split with one space.') do |v|
128
- @options[:raw] = v
127
+ opts.on('-o FORMAT', '--output-format FORMAT', %i[pretty raw json],
128
+ 'Output format. FORMAT should be one of <pretty|raw|json>.', 'Default: pretty') do |o|
129
+ @options[:format] = o
130
+ end
131
+
132
+ opts.on('-r', '--raw', 'Alias of -o raw. Output gadgets offset only, split with one space.') do |_|
133
+ @options[:format] = :raw
129
134
  end
130
135
 
131
136
  opts.on('-s', '--script exploit-script', 'Run exploit script with all possible gadgets.',
@@ -176,14 +181,19 @@ module OneGadget
176
181
 
177
182
  # Writes gadgets to stdout.
178
183
  # @param [Array<OneGadget::Gadget::Gadget>] gadgets
179
- # @param [Boolean] raw
180
- # In raw mode, only the offset of gadgets are printed.
184
+ # @param [Symbol] format
185
+ # :raw - Only the offset of gadgets are printed.
186
+ # :pretty - Colorful and human-readable format.
187
+ # :json - In JSON format.
181
188
  # @return [true]
182
- def display_gadgets(gadgets, raw)
183
- if raw
189
+ def display_gadgets(gadgets, format)
190
+ case format
191
+ when :raw
184
192
  show(gadgets.map(&:value).join(' '))
185
- else
193
+ when :pretty
186
194
  show(gadgets.map(&:inspect).join("\n"))
195
+ when :json
196
+ show(gadgets.to_json)
187
197
  end
188
198
  end
189
199
 
@@ -199,7 +209,7 @@ module OneGadget
199
209
  # @param [String] libc_file
200
210
  # @param [Array<OneGadget::Gadget::Gadget>] gadgets
201
211
  # @param [String] near
202
- # This can be name of functions or an ELF file.
212
+ # Either name of functions or path to an ELF file.
203
213
  # - Use one comma without spaces to specify a list of functions: +printf,scanf,free+.
204
214
  # - Path to an ELF file and take its GOT functions to process: +/bin/ls+
205
215
  def handle_near(libc_file, gadgets, near)
@@ -213,10 +223,19 @@ module OneGadget
213
223
  function_offsets = OneGadget::Helper.function_offsets(libc_file, functions)
214
224
  return error('No functions for processing') if function_offsets.empty?
215
225
 
216
- function_offsets.each do |function, offset|
217
- colored_offset = OneGadget::Helper.colored_hex(offset)
218
- OneGadget::Logger.warn("Gadgets near #{OneGadget::Helper.colorize(function)}(#{colored_offset}):")
219
- display_gadgets(gadgets.sort_by { |gadget| (gadget.offset - offset).abs }, @options[:raw])
226
+ collection = function_offsets.map do |function, offset|
227
+ {
228
+ near: function,
229
+ near_offset: offset,
230
+ gadgets: gadgets.sort_by { |gadget| (gadget.offset - offset).abs }
231
+ }
232
+ end
233
+ return show(collection.to_json) if @options[:format] == :json
234
+
235
+ collection.each do |c|
236
+ colored_offset = OneGadget::Helper.colored_hex(c[:near_offset])
237
+ OneGadget::Logger.warn("Gadgets near #{OneGadget::Helper.colorize(c[:near])}(#{colored_offset}):")
238
+ display_gadgets(c[:gadgets], @options[:format])
220
239
  show("\n")
221
240
  end
222
241
  true
@@ -18,8 +18,8 @@ module OneGadget
18
18
 
19
19
  # @see OneGadget::Emulators::X86#process!
20
20
  def process!(cmd)
21
- inst, args = parse(cmd.gsub(/#-?(0x)?[0-9a-f]+/) { |v| v[1..-1] })
22
- sym = "inst_#{inst.inst}".to_sym
21
+ inst, args = parse(cmd.gsub(/#-?(0x)?[0-9a-f]+/) { |v| v[1..] })
22
+ sym = :"inst_#{inst.inst}"
23
23
  __send__(sym, *args) != :fail
24
24
  end
25
25
 
@@ -31,7 +31,7 @@ module OneGadget
31
31
  idx = cmd.index(inst)
32
32
  cmd = cmd[0...cmd.rindex('//')] if cmd.rindex('//')
33
33
  cmd = cmd[0...cmd.rindex('#')] if cmd.rindex('#')
34
- args = parse_args(cmd[idx + inst.size..-1])
34
+ args = parse_args(cmd[idx + inst.size..])
35
35
  unless argc.include?(args.size)
36
36
  raise OneGadget::Error::InstructionArgumentError, "Incorrect argument number in #{cmd}, expect: #{argc}"
37
37
  end
@@ -43,7 +43,7 @@ module OneGadget
43
43
  # @param [Numeric] other Value to substract.
44
44
  # @return [Lambda] The result.
45
45
  def -(other)
46
- self.+(-other)
46
+ self + -other
47
47
  end
48
48
 
49
49
  # Increase dereference count by 1.
@@ -123,8 +123,8 @@ module OneGadget
123
123
  # nested []
124
124
  if arg[0] == '['
125
125
  ridx = arg.rindex(']')
126
- immi = parse(arg[(ridx + 1)..-1])
127
- lm = parse(arg[1...ridx], predefined: predefined).deref
126
+ immi = parse(arg[(ridx + 1)..])
127
+ lm = parse(arg[1...ridx], predefined:).deref
128
128
  lm += immi unless immi.zero?
129
129
  return lm
130
130
  end
@@ -19,7 +19,7 @@ module OneGadget
19
19
  # @param [String] sp
20
20
  # The stack register.
21
21
  def initialize(registers, sp)
22
- @registers = registers.map { |reg| [reg, to_lambda(reg)] }.to_h
22
+ @registers = registers.to_h { |reg| [reg, to_lambda(reg)] }
23
23
  @sp = sp
24
24
  @constraints = []
25
25
  @sp_based_stack = Hash.new do |h, k|
@@ -36,7 +36,7 @@ module OneGadget
36
36
  # return registers[pc] = args[0] if inst.inst == 'call'
37
37
  return true if inst.inst == 'jmp' # believe the fetcher has handled jmp.
38
38
 
39
- sym = "inst_#{inst.inst}".to_sym
39
+ sym = :"inst_#{inst.inst}"
40
40
  __send__(sym, *args) != :fail
41
41
  end
42
42
 
@@ -20,7 +20,7 @@ module OneGadget
20
20
  # +nil+ is returned if cannot find target id in database.
21
21
  def from_build_id(build_id, remote: true)
22
22
  OneGadget::Helper.verify_build_id!(build_id)
23
- OneGadget::Gadget.builds(build_id, remote: remote)
23
+ OneGadget::Gadget.builds(build_id, remote:)
24
24
  end
25
25
 
26
26
  # Fetch one-gadget offsets from file.
@@ -28,7 +28,7 @@ module OneGadget
28
28
  # use processor to find which can lead to a valid one-gadget call.
29
29
  gadgets = []
30
30
  (lines.size - 2).downto(0) do |i|
31
- processor = emulate(lines[i..-1])
31
+ processor = emulate(lines[i..])
32
32
  options = resolve(processor)
33
33
  next if options.nil? # impossible to be a gadget
34
34
 
@@ -48,7 +48,7 @@ module OneGadget
48
48
  # True for valid.
49
49
  # @return [Array<String>]
50
50
  # Each +String+ returned is multi-lines of assembly code.
51
- def candidates(&block)
51
+ def candidates(&)
52
52
  call_regexp = "#{call_str}.*<(exec[^+]*|posix_spawn[^+]*)>$"
53
53
  cands = []
54
54
  `#{@objdump.command}|grep -E '#{call_regexp}' -B 30`.split('--').each do |cand|
@@ -63,7 +63,7 @@ module OneGadget
63
63
  end
64
64
  # remove all jmps
65
65
  cands = slice_prefix(cands, &method(:branch?))
66
- cands.select!(&block) if block_given?
66
+ cands.select!(&) if block_given?
67
67
  cands
68
68
  end
69
69
 
@@ -81,7 +81,8 @@ module OneGadget
81
81
  call = processor.registers[processor.pc].to_s
82
82
  return resolve_posix_spawn(processor) if call.include?('posix_spawn')
83
83
  return resolve_execve(processor) if call.include?('execve')
84
- return resolve_execl(processor) if call.include?('execl')
84
+
85
+ resolve_execl(processor) if call.include?('execl')
85
86
  end
86
87
 
87
88
  def resolve_execve(processor)
@@ -110,7 +111,7 @@ module OneGadget
110
111
  envp = arg2
111
112
  end
112
113
 
113
- { constraints: cons, envp: envp }
114
+ { constraints: cons, envp: }
114
115
  end
115
116
 
116
117
  def check_argv(processor, arg, allow_null)
@@ -282,7 +283,7 @@ module OneGadget
282
283
  cands.map do |cand|
283
284
  lines = cand.lines
284
285
  to_rm = lines[0...-1].rindex(&block)
285
- lines = lines[to_rm + 1..-1] unless to_rm.nil?
286
+ lines = lines[to_rm + 1..] unless to_rm.nil?
286
287
  lines.join
287
288
  end
288
289
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
3
5
  require 'one_gadget/abi'
4
6
  require 'one_gadget/emulators/lambda'
5
7
  require 'one_gadget/error'
@@ -28,13 +30,12 @@ module OneGadget
28
30
  @base = 0
29
31
  @offset = offset
30
32
  @constraints = options[:constraints] || []
31
- @effect = options[:effect]
33
+ @effect = options[:effect] || ''
32
34
  end
33
35
 
34
36
  # Show gadget in a pretty way.
35
37
  def inspect
36
- str = OneGadget::Helper.hex(value)
37
- str += effect ? " #{effect}\n" : "\n"
38
+ str = "#{OneGadget::Helper.hex(value)} #{effect}\n"
38
39
  unless constraints.empty?
39
40
  str += "#{OneGadget::Helper.colorize('constraints')}:\n "
40
41
  str += merge_constraints.join("\n ")
@@ -46,6 +47,21 @@ module OneGadget
46
47
  "#{str}\n"
47
48
  end
48
49
 
50
+ # @return [Hash]
51
+ def to_obj
52
+ {
53
+ value:,
54
+ effect:,
55
+ constraints:
56
+ }
57
+ end
58
+
59
+ # To have this class can be serialized in JSON.
60
+ # @return [String]
61
+ def to_json(*)
62
+ to_obj.to_json
63
+ end
64
+
49
65
  # @return [Integer]
50
66
  # Returns +base+ plus +offset+.
51
67
  def value
@@ -112,7 +128,7 @@ module OneGadget
112
128
  w_cons, normal = constraints.partition { |c| c.start_with?(key) }
113
129
  return normal if w_cons.empty?
114
130
 
115
- w_cons.map! { |c| c[key.size..-1] }
131
+ w_cons.map! { |c| c[key.size..] }
116
132
  ["address#{w_cons.size > 1 ? 'es' : ''} #{w_cons.join(', ')} #{w_cons.size > 1 ? 'are' : 'is'} writable"] +
117
133
  normal
118
134
  end
@@ -161,7 +177,7 @@ module OneGadget
161
177
  def builds_info(build_id)
162
178
  raise Error::ArgumentError, "Invalid BuildID #{build_id.inspect}" if build_id =~ /[^0-9a-f]/
163
179
 
164
- files = Dir.glob(File.join(BUILDS_PATH, "*-#{build_id}*.rb")).sort
180
+ files = Dir.glob(File.join(BUILDS_PATH, "*-#{build_id}*.rb"))
165
181
  return OneGadget::Logger.not_found(build_id) && nil if files.empty?
166
182
 
167
183
  if files.size > 1
@@ -189,7 +205,7 @@ module OneGadget
189
205
  def find_build(id)
190
206
  return BUILDS[id] if BUILDS.key?(id)
191
207
 
192
- Dir.glob(File.join(BUILDS_PATH, "*-#{id}.rb")).sort.each do |dic|
208
+ Dir.glob(File.join(BUILDS_PATH, "*-#{id}.rb")).each do |dic|
193
209
  require dic
194
210
  end
195
211
  BUILDS[id] if BUILDS.key?(id)
@@ -13,7 +13,7 @@ module OneGadget
13
13
  # Define some helpful methods here.
14
14
  module Helper
15
15
  # Format of build-id, 40 hex numbers.
16
- BUILD_ID_FORMAT = /[0-9a-f]{40}/.freeze
16
+ BUILD_ID_FORMAT = /[0-9a-f]{40}/
17
17
 
18
18
  module_function
19
19
 
@@ -35,7 +35,7 @@ module OneGadget
35
35
  # @return [Array<String>]
36
36
  # Lines of comments.
37
37
  def comments_of_file(file)
38
- File.readlines(file).map { |s| s[2..-1].rstrip if s.start_with?('# ') }.compact
38
+ File.readlines(file).map { |s| s[2..].rstrip if s.start_with?('# ') }.compact
39
39
  end
40
40
 
41
41
  # Get absolute path from relative path. Support symlink.
@@ -24,14 +24,14 @@ module OneGadget
24
24
  FileUtils.touch(cache_file)
25
25
  OneGadget::Logger.info("Checking for new versions of OneGadget\n" \
26
26
  "To disable this functionality, do\n$ echo never > #{CACHE_FILE}\n\n")
27
- latest = Helper.latest_tag[1..-1] # remove 'v'
27
+ latest = Helper.latest_tag[1..] # remove 'v'
28
28
  if Gem::Version.new(latest) <= Gem::Version.new(OneGadget::VERSION)
29
29
  return OneGadget::Logger.info("You have the latest version of OneGadget (#{latest})!\n\n")
30
30
  end
31
31
 
32
32
  # show update message
33
33
  msg = format('A newer version of OneGadget is available (%s --> %s).', OneGadget::VERSION, latest)
34
- OneGadget::Logger.ask_update(msg: msg)
34
+ OneGadget::Logger.ask_update(msg:)
35
35
  end
36
36
 
37
37
  private
@@ -2,5 +2,5 @@
2
2
 
3
3
  module OneGadget
4
4
  # Current gem version.
5
- VERSION = '1.9.0'
5
+ VERSION = '1.10.0'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: one_gadget
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - david942j
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-29 00:00:00.000000000 Z
11
+ date: 2024-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: elftools
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 1.0.2
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 1.2.0
22
+ version: 1.4.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 1.0.2
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 1.2.0
32
+ version: 1.4.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rake
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -1014,14 +1014,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
1014
1014
  requirements:
1015
1015
  - - ">="
1016
1016
  - !ruby/object:Gem::Version
1017
- version: '2.4'
1017
+ version: '3.1'
1018
1018
  required_rubygems_version: !ruby/object:Gem::Requirement
1019
1019
  requirements:
1020
1020
  - - ">="
1021
1021
  - !ruby/object:Gem::Version
1022
1022
  version: '0'
1023
1023
  requirements: []
1024
- rubygems_version: 3.1.6
1024
+ rubygems_version: 3.5.3
1025
1025
  signing_key:
1026
1026
  specification_version: 4
1027
1027
  summary: one_gadget