x/16i 0xdeadbeef yields:
0x80481be <_init+22>: shlb $0x3a,-0x18(%ebp,%eax,1)
0x80481c3 <_init+27>: jle 0x80481c0 <_init+24>
0x80481c5 <_init+29>: .byte 0xf7
0x80481c6 <_init+30>: add $0x8,%esp
0x80481c9 <_init+33>: pop %ebx
0x80481ca <_init+34>: ret
where init+22-27 has some juicy instructions "inside" it, if only I could see what they were.
x/16s 0xdeadbeef yields:
0x80481be <_init+22>: "\300t\005\350:~\373\367\203\304\b"
which isn't very interesting.
I'm writing a ROP chain generator, so I need to find instructions that can be executed by jumping into the "middle" of other instructions. The (very) slow way is to simply run x/i 0xdeadbeef; x/i 0xdeadbef0, .... Is there a faster way?
I've tried x/i+<offset> 0xdeadbeef: the first instruction that yields is in the middle of x/i 0xdeadbeef, but subsequent instructions aren't "indexed into the middle of", making this way the same as the slow way.
GDB is designed for normal use-cases of debugging code the CPU will execute, so disassembly of the next instruction starts at the end of the previous. If you're looking mostly manually, by eye, you might define a GDB function to disassemble a short sequence starting at every byte offset in a range. You can enter this directly (one line at a time) on GDB's interactive command line, or I think put it in your
.gdbinitor a in file you source.This defines a function that takes 2 args: start address, and length in bytes of disassembly from each starting byte.
You could also parameterize the length (32 bytes) to search as
$arg2. See the GDB manual (https://sourceware.org/gdb/current/onlinedocs/gdb.html/Define.html), it has examples.In interactive use, this looks like:
abortwas just a symbol name that appeared early inobjdump -drwC -Mintel /lib/libc.so.6 | less. My.gdbinitusesset disassembly-flavor intel.So it's noisy, 2 lines of start/end "of assembler dump" around every block, but that's not so bad when looking at blocks of multiple instructions. (GDB will disassemble to the end of an instruction is the disas range includes the first byte.)
What matters is the sequence of instructions the CPU will execute from any given start point so I used a 16-byte range, rather than just
1to see the instruction you get at a given start point.Of course this isn't filtering for sequences that end with
retorpop reg/jmp reg. Probably it's possible to do that with GDB commands. Or there are disassembler libraries like capstone and XED if you want to write a whole program to analyze a chunk of machine code you paste, or even to search bytes in executables and libraries, or in running processes.x86 machine code is a byte stream that's not self-synchronizing, but does decode uniquely from a given starting point. For typical use-cases, it's not useful to see how it would have decoded if a jump target address had been wrong. GDB doesn't have an option to do that.
Despite not being truly self-synchronizing (you can't look at a byte and see if it's the start or end of an instruction or not), quite a few bytes are prefixes or opcodes for single-byte instructions, so re-sync usually happens within 2 to 10 bytes. This means the could be quite a bit of duplication in the simple GDB function I wrote; IDK if you'd want to filter that out or not. Probably not, just see all the different options that lead to a
ret.