Author Topic: ndisasm then nasm not idempotent  (Read 3511 times)

Offline ncw

  • Jr. Member
  • *
  • Posts: 3
ndisasm then nasm not idempotent
« on: May 08, 2014, 10:32:50 AM »
I've noticed that if I disassemble some code, then reassemble it, I get back different code from where I started! This isn't particularly worrying, but I was wondering if this was intentional?

Here's a harmless example:

Code: [Select]
$ printf '\x3b\xc8' | ndisasm -u /dev/stdin
00000000  3BC8              cmp ecx,eax
$ printf 'BITS 32\ncmp ecx,eax' > tmp; nasm tmp -f bin -o /dev/stdout | ndisasm -u /dev/stdin
00000000  39C1              cmp ecx,eax

Here's a more worrying example, where the size of the instruction changes, which means later jump offset will be wrong (ie disassembling then reassembling breaks the code):

Code: [Select]
$ printf '\x75\x03' | ndisasm -u /dev/stdin
00000000  7503              jnz 0x5
$ printf 'BITS 32\njnz 0x5' > tmp; nasm tmp -f bin -o /dev/stdout | ndisasm -u /dev/stdin
00000000  0F85FFFFFFFF      jnz dword 0x5

Yikes! On the other hand, watch what happens for straight jmp instructions:

Code: [Select]
$ printf '\xeb\x18' | ndisasm -u /dev/stdin
00000000  EB18              jmp short 0x1a
$ printf 'BITS 32\njmp short 0x1a' > tmp; nasm tmp -f bin -o /dev/stdout | ndisasm -u /dev/stdin
00000000  EB18              jmp short 0x1a

So, why is it that ndisasm generates "jmp short ...", but just "jnz ..."? If ndisasm were to output instead "jnz short ..." for my example, as it does for jmp, then it might generate less surprise! I'm not experienced with assembler, so maybe there's some difference between the instructions I'm unaware of that explains the behaviour.

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 430
  • Country: us
Re: ndisasm then nasm not idempotent
« Reply #1 on: May 08, 2014, 03:28:03 PM »
You are feeding ndisasm hand-crafted opcodes directly but you feed nasm the assembler source.  The outputs result in identical behavior, but since nasm was told to assemble with BITS 32 and has no further information to go by it generates the code as specified.  I'm not seeing an issue here.

Offline ncw

  • Jr. Member
  • *
  • Posts: 3
Re: ndisasm then nasm not idempotent
« Reply #2 on: May 09, 2014, 10:11:45 AM »
The issue is that ndisasm isn't outputting instructions as specific as it could: if it output "jne short ..." instead of "jne ..." for the opcodes given, then reassembling would preserve the input.

ndisasm has this nice behaviour for plain "jmp" instructions though, outputting "jmp short ..." as expected, so that nasm reassembles with the same opcodes. I'm still wondering why ndisasm behaves differently for jmp and jne instructions.

My task is patching some compiled code -- I just want to disassemble it, tweak it, then reassemble it. I hadn't expected that process would change the behaviour of the code, that's all (recoding a jump with an "equivalent" instruction that has a different width to the original one *does* change the behaviour of the code).

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2436
  • Country: us
Re: ndisasm then nasm not idempotent
« Reply #3 on: May 09, 2014, 11:03:10 AM »
See if Agner Fog's "objconv" will suit your purposes better...

http://www.agner.org/optimize/#objconv

Best,
Frank


Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 430
  • Country: us
Re: ndisasm then nasm not idempotent
« Reply #4 on: May 09, 2014, 03:32:35 PM »
Binary object manipulation - reference your favorite debugger.  I hear OllyDbg is useful in some circles.

Offline ncw

  • Jr. Member
  • *
  • Posts: 3
Re: ndisasm then nasm not idempotent
« Reply #5 on: May 12, 2014, 09:44:51 AM »
Thanks for the pointers folks!