NASM - The Netwide Assembler

NASM Forum => Using NASM => Topic started by: ncw on May 08, 2014, 10:32:50 AM

Title: ndisasm then nasm not idempotent
Post by: ncw 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.
Title: Re: ndisasm then nasm not idempotent
Post by: Rob Neff 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.
Title: Re: ndisasm then nasm not idempotent
Post by: ncw 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).
Title: Re: ndisasm then nasm not idempotent
Post by: Frank Kotler 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

Title: Re: ndisasm then nasm not idempotent
Post by: Rob Neff on May 09, 2014, 03:32:35 PM
Binary object manipulation - reference your favorite debugger.  I hear OllyDbg is useful in some circles.
Title: Re: ndisasm then nasm not idempotent
Post by: ncw on May 12, 2014, 09:44:51 AM
Thanks for the pointers folks!