NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started 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:
$ 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):
$ 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:
$ 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.
-
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.
-
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).
-
See if Agner Fog's "objconv" will suit your purposes better...
http://www.agner.org/optimize/#objconv
Best,
Frank
-
Binary object manipulation - reference your favorite debugger. I hear OllyDbg is useful in some circles.
-
Thanks for the pointers folks!