Sawb
Sawb

Reputation: 67

Why can there be assembly code between a jmp statement?

Sometimes I see code that should never be reached because of a jmp statement.

example:

0004036F call program.48391
00040374 jmp program.40440
00040376 lea rdx,qword ptr ds:[stringaddress]
....
....
.... //code that does something else
....
....
00040440 mov ebx,0

What is going on here, why is there code and how is it ever reached?

Upvotes: 1

Views: 263

Answers (1)

old_timer
old_timer

Reputation: 71546

My x86 is super rusty, but being a variable length instruction set it is very difficult to disassemble, and one should expect some percentage of the disassembly output to be (completely) wrong forever or for a period of time (number of instructions in linear order). The only correct way to disassemble is to do it in execution order not linear memory order, but then that would leave gaps of what could be real code. Anyway, so unless my code is buggy functionally, it still demonstrates how a jump can be used.

mov 0x4,%eax
jmp over
under:
  dec %eax
over:
  test %eax,%eax
  jne under

Disassembly of section .text:

0000000000000000 <.text>:
   0:   8b 04 25 04 00 00 00    mov    0x4,%eax
   7:   eb 02                   jmp    0xb
   9:   ff c8                   dec    %eax
   b:   85 c0                   test   %eax,%eax
   d:   75 fa                   jne    0x9

but because it is variable length you can have perfectly working code, that the disassembler completely messes up.

mov 0x4,%eax
jmp over
.byte 0x22
under:
  dec %eax
over:
  test %eax,%eax
  jne under

0000000000000000 <.text>:
   0:   8b 04 25 04 00 00 00    mov    0x4,%eax
   7:   eb 03                   jmp    0xc
   9:   22 ff                   and    %bh,%bh
   b:   c8 85 c0 75             enterq $0xc085,$0x75
   f:   fa                      cli 

There isn't even a landing spot for 0xc; since they showed me a single byte instruction I'll just use that:

mov 0x4,%eax
jmp over
.byte 0xfa
under:
  dec %eax
over:
  test %eax,%eax
  jne under

0000000000000000 <.text>:
   0:   8b 04 25 04 00 00 00    mov    0x4,%eax
   7:   eb 03                   jmp    0xc
   9:   fa                      cli    
   a:   ff c8                   dec    %eax
   c:   85 c0                   test   %eax,%eax
   e:   75 fa                   jne    0xa

The machine code for the actual instructions is identical so the one with the bad disassembly was correctly generated machine code, it was just the disassembler was messed up because it disassembled in memory order rather than execution order, an extremely common disassembler approach (with semi-valid reasons).

In this case I had to play some tricks to upset the gnu disassembler, they leave themselves breadcrumbs outside the machine code in the binary to make this a bit more successful, but you can still trip up the disassembler if you put more work into it (I stopped trying with such a simple example).

mov 0x4,%eax
jmp over
.byte 0x22
under:
  dec %eax
over:
  test %eax,%eax
  jne under

0000000000000000 <under-0xa>:
   0:   8b 04 25 04 00 00 00    mov    0x4,%eax
   7:   eb 03                   jmp    c <over>
   9:   22                      .byte 0x22

000000000000000a <under>:
   a:   ff c8                   dec    %eax

000000000000000c <over>:
   c:   85 c0                   test   %eax,%eax
   e:   75 fa                   jne    a <under>

It appears they are using the labels to reset the disassembler.

mov 0x4,%eax
jmp over
.byte 0x22
/*under:*/
  dec %eax
over:
  test %eax,%eax
  .byte 0x75,0xFA /* jne under*/

0000000000000000 <over-0xc>:
   0:   8b 04 25 04 00 00 00    mov    0x4,%eax
   7:   eb 03                   jmp    c <over>
   9:   22 ff                   and    %bh,%bh
   b:   c8                      .byte 0xc8

000000000000000c <over>:
   c:   85 c0                   test   %eax,%eax
   e:   75 fa                   jne    a <over-0x2>

Anyway, hopefully Margaret's comment makes more sense.

Upvotes: 4

Related Questions