Hex to Asm and Asm to Hex

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, i hope you give me a hand on this.

 

what i want to do is, read flash --> disassemble hex file ---> modify Asm file --> generate hex file --> upload it to the microcontroller(Arduino uno=atmega328p)

 

im using the blink sketch for testing. i would like to modify the delay.

 

 

Im reading hex file with Avrdude, i have no problem doing this.(why it fills the file with .byte 1 to complete the space left ? IDA also does this)

 

im using atmel studio to compile the asm file and generate the final hex file.

 

 

i have used different options to disassemble the hex file.

 

1. IDA PRO 

 

of course i got some compiling errors, for example

 

undefined symbols errors, i just check in the other disassemble asm files to correct them.

 

lds    r24, unk_100101 ---- > lds    r24, 0x0101

call    nullsub_1 ---- > call   avr01F0 (i createed this macro according to another asm file)

 

etc... at the end , i build the project with no errors, and upload it to the arduino, but it doesnt work,  led keeps on for ever.

 

 

2. AVR-OBJDUMP

 

here i got errors like this:

 

syntax error, unexpected $undefined

 

rjmp    .-44  -- > rjmp PC -4 ( i read somewhere in this forum is becase different versions of disassembler)

 

rjmp   .+4 ---> rjmp    PC+4

 

Relative branch out of reach

breq    PC+82 ----> breq  avr01B7(i also created this macro avr01B7) (avr01B7:  pop    YH           ; 01B7 91DF)

 

i build no error, but it doesnt work, led keeps on.

 

 

3.DISAVR

 

in r18, ?0x26? ---->in r18, 0x26

 

movw r14 r24  ----> movw r14, r24

 

in r24, ICR1L  ---> in r24, 0x24 (i saw this in avr-objdmp asm file)

 

rjmp $ ---> rjmp PC-2

 

also had to change in by lds or out by sts im some cases.

 

 

but i got the same result.

 

 

i havent even modify the asm file to make a longer delay, and its not even working.

 

what could be the problem ?

 

THANKS!!

 

 

 

 

Attachment(s): 

Last Edited: Sun. Jun 21, 2015 - 05:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why don't you examine the starting program for hints, and then create your own ASM program?

 

Disassemblers can never do the complete job, as you have found.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

because im thinking about an scenerario where i dont have access to the starting program.

Last Edited: Sun. Jun 21, 2015 - 05:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ColAvrFreak wrote:
because im thinking about an scenerario where i dont have access to the starting program.
If you wrote the program, surely you'll have the source code.

 

If you have permission to modify someone else's program, surely you'll have the source code.

 

If you have neither of those things, surely you can't expect anyone here to help you steal someone else's work.

 

As for the feasibility of reverse engineering a hex file, it's a bit like reverse engineering a cake.  Yes it can be done.  Getting it exactly right is a painstaking task.  If the hex file is the result of a heavily optimising compiler like GCC, good luck to you.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it just came to my mind the idea of doing that and i wanted to see if it was posible or how hard it could be... thats it...frown

Last Edited: Mon. Jun 22, 2015 - 02:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For learning purposes, you8 can take your sketch and generate the .LSS file, which will correspond what you found with the annotated source.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ColAvrFreak wrote:

what i want to do is, read flash --> disassemble hex file ---> modify Asm file --> generate hex file --> upload it to the microcontroller(Arduino uno=atmega328p)

 

im using the blink sketch for testing. i would like to modify the delay.

 

As you have found out, doing a full DisAsm and ReAsm is non-trivial, and depends on the tools.

 

Simpler to do what you seek, is instead to create a smart HEX editor - if you just want to modify the delay, that is 2 or 3 locations to patch in a HEX file.  No disasm or asm needed.

 

You can give the software the bytes addresses, and rules to use, or have it search for delay code blocks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As mentioned, what you want to do takes some experience. As you've found, it takes some fiddling and a lot of time.
As to why your reassembled code doesn't work, compare the binaries and identify the difference. Work that back to the asm. Assemble and repeat. When they are identical you know you've got it correct.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does the IDA PRO disassembler work on PC, Mac, and/or Linux code that is tied to the PC platform?   Looking at the IDA PRO website I don't see any indication that this program disassembles Atmel AVR code.

 

Try writing the blink program with an unusual delay value, like 0xAA.  Then search the code for the byte that is your delay value.  Change that value.  Reload into the AVR and see if the delay has changed.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Try writing the blink program with an unusual delay value, like 0xAA.  Then search the code for the byte that is your delay value.  Change that value.  Reload into the AVR and see if the delay has changed.
That might prove difficult.  The 'normal' delay routines in <util/delay.h> combine with F_CPU to compute a number of cpu cycles.  That is then passed to __builtin_avr_delay_cycles() which builds a cycle-accurate code block based on one of four loop primitives (3-, 4-, 5-, and 6-cycle), and a 2-cycle and 1-cycle primitive.  Any value passed to _delay_ms() or _delay_us() is not likely to make an appearance anywhere in the hex file.

 

Use of the routines in <util/delay_basic.h> might prove more useful.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:

Does the IDA PRO disassembler work on PC, Mac, and/or Linux code that is tied to the PC platform?   Looking at the IDA PRO website I don't see any indication that this program disassembles Atmel AVR code.

 

Try writing the blink program with an unusual delay value, like 0xAA.  Then search the code for the byte that is your delay value.  Change that value.  Reload into the AVR and see if the delay has changed.

 

 

yes, you can do it with IDA PRO.

Last Edited: Mon. Jun 22, 2015 - 02:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks everybody for the tips and info!.yes

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As I haven't see the suggestion elsewhere in the thread yet can I just mention -save-temps.

 

Now if this is code being built in Arduino (the use of the word "sketch" suggests yes) then I'm not sure how easy it is to add custom commands to the compilation step. But if you can try adding -save-temps. When foo.c or foo.cpp is built this will lead to a file called foo.s being created. Like the .lss file this is the Asm version of the C/C++ you are building but the difference between this and the .lss is that it is "clean" Asm source that can easily be modified then used to build the code (that's exactly what C/C++ compilation does - converts the source to assembler then assembles it using avr-as).

 

So if you want to "tinker" with the Asm of a C program just use -save-temps then take the generated .s file as the starting point for your "tinkering". Here's an example:

$ cat avr.c
#define F_CPU 3686400UL
#include <avr/io.h>
#include <util/delay.h>

int main(void) {
	DDRB = 0xFF;
	while(1) {
		PORTB ^= 0xFF;
		_delay_ms(200);
	}
}
$ avr-gcc -mmcu=atmega16 -Os -save-temps avr.c -o avr.elf
$ cat avr.s
	.file	"avr.c"
__SREG__ = 0x3f
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__CCP__ = 0x34
__tmp_reg__ = 0
__zero_reg__ = 1
	.text
.global	main
	.type	main, @function
main:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
	ldi r24,lo8(-1)
	out 55-32,r24
.L2:
	in r24,56-32
	com r24
	out 56-32,r24
	 ldi r24,lo8(147455)
    ldi r25,hi8(147455)
    ldi r26,hlo8(147455)
    1:subi r24,1
    sbci r25,0
    sbci r26,0
    brne 1b
	rjmp .
	nop
	rjmp .L2
	.size	main, .-main

In this you can see that the call to _delay_ms(200) in the source (also based on the 3.6864MHz CPU speed) has generated a loop that counts to 147455 (0x023FFF) . If I look at the lss:

	__builtin_avr_delay_cycles(__ticks_dc);
  76:	8f ef       	ldi	r24, 0xFF	; 255
  78:	9f e3       	ldi	r25, 0x3F	; 63
  7a:	a2 e0       	ldi	r26, 0x02	; 2

You can just about see the 0x023FFF encoded in there but the nibbles are embedded into LDI opcodes and are in the "wrong order". You could see this in the .hex:

$ cat avr.hex
:100000000C942A000C9434000C9434000C943400AA
:100010000C9434000C9434000C9434000C94340090
:100020000C9434000C9434000C9434000C94340080
:100030000C9434000C9434000C9434000C94340070
:100040000C9434000C9434000C9434000C94340060
:100050000C94340011241FBECFE5D4E0DEBFCDBF29
:100060000E9436000C9445000C9400008FEF87BB73
:1000700088B3809588BB8FEF9FE3A2E081509040CA
:0E008000A040E1F700C00000F3CFF894FFCFDE
:00000001FF

Trying to find/change this is actually pretty tricky. While you can do this:

$ avr-objdump -mavr -D avr.hex

avr.hex:     file format ihex


Disassembly of section .sec1:

00000000 <.sec1>:
   0:	0c 94 2a 00 	jmp	0x54	;  0x54
   4:	0c 94 34 00 	jmp	0x68	;  0x68
   8:	0c 94 34 00 	jmp	0x68	;  0x68
   c:	0c 94 34 00 	jmp	0x68	;  0x68
  10:	0c 94 34 00 	jmp	0x68	;  0x68
  14:	0c 94 34 00 	jmp	0x68	;  0x68
  18:	0c 94 34 00 	jmp	0x68	;  0x68
  1c:	0c 94 34 00 	jmp	0x68	;  0x68
  20:	0c 94 34 00 	jmp	0x68	;  0x68
  24:	0c 94 34 00 	jmp	0x68	;  0x68
  28:	0c 94 34 00 	jmp	0x68	;  0x68
  2c:	0c 94 34 00 	jmp	0x68	;  0x68
  30:	0c 94 34 00 	jmp	0x68	;  0x68
  34:	0c 94 34 00 	jmp	0x68	;  0x68
  38:	0c 94 34 00 	jmp	0x68	;  0x68
  3c:	0c 94 34 00 	jmp	0x68	;  0x68
  40:	0c 94 34 00 	jmp	0x68	;  0x68
  44:	0c 94 34 00 	jmp	0x68	;  0x68
  48:	0c 94 34 00 	jmp	0x68	;  0x68
  4c:	0c 94 34 00 	jmp	0x68	;  0x68
  50:	0c 94 34 00 	jmp	0x68	;  0x68
  54:	11 24       	eor	r1, r1
  56:	1f be       	out	0x3f, r1	; 63
  58:	cf e5       	ldi	r28, 0x5F	; 95
  5a:	d4 e0       	ldi	r29, 0x04	; 4
  5c:	de bf       	out	0x3e, r29	; 62
  5e:	cd bf       	out	0x3d, r28	; 61
  60:	0e 94 36 00 	call	0x6c	;  0x6c
  64:	0c 94 45 00 	jmp	0x8a	;  0x8a
  68:	0c 94 00 00 	jmp	0	;  0x0
  6c:	8f ef       	ldi	r24, 0xFF	; 255
  6e:	87 bb       	out	0x17, r24	; 23
  70:	88 b3       	in	r24, 0x18	; 24
  72:	80 95       	com	r24
  74:	88 bb       	out	0x18, r24	; 24
  76:	8f ef       	ldi	r24, 0xFF	; 255
  78:	9f e3       	ldi	r25, 0x3F	; 63
  7a:	a2 e0       	ldi	r26, 0x02	; 2
  7c:	81 50       	subi	r24, 0x01	; 1
  7e:	90 40       	sbci	r25, 0x00	; 0
  80:	a0 40       	sbci	r26, 0x00	; 0
  82:	e1 f7       	brne	.-8      	;  0x7c
  84:	00 c0       	rjmp	.+0      	;  0x86
  86:	00 00       	nop
  88:	f3 cf       	rjmp	.-26     	;  0x70
  8a:	f8 94       	cli
  8c:	ff cf       	rjmp	.-2      	;  0x8c

The address/opcode bytes there mean this code cannot be easily re-assembled. However back at the .s file that I created using -save-temps, say I want to double the speed of the LED flashing by halving the delay from 147,455 to 73,728, I could just do this:

$ sed 's/147455/73728/' avr.s > avrupdate.S
$ avr-gcc -mmcu=atmega16 avrupdate.S -o avr.elf
$ avr-objdump -j .text  -D avr.elf | tail -n 18
  72:	80 95       	com	r24
  74:	88 bb       	out	0x18, r24	; 24
  76:	80 e0       	ldi	r24, 0x00	; 0
  78:	90 e2       	ldi	r25, 0x20	; 32
  7a:	a1 e0       	ldi	r26, 0x01	; 1
  7c:	81 50       	subi	r24, 0x01	; 1
  7e:	90 40       	sbci	r25, 0x00	; 0
  80:	a0 40       	sbci	r26, 0x00	; 0
  82:	e1 f7       	brne	.-8      	; 0x7c <main+0x10>
  84:	00 c0       	rjmp	.+0      	; 0x86 <main+0x1a>
  86:	00 00       	nop
  88:	f3 cf       	rjmp	.-26     	; 0x70 <main+0x4>

0000008a <_exit>:
  8a:	f8 94       	cli

0000008c <__stop_program>:
  8c:	ff cf       	rjmp	.-2      	; 0x8c <__stop_program>

And here I have modified the source to change 0x023FFF to be 0x012000, built it from the Asm (.S) and the disassembled the code once built to reveal that my delay change to 0x012000 has worked.

 

Bottom line: explore the world of -save-temps

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who-me wrote:
Simpler to do what you seek, is instead to create a smart HEX editor - if you just want to modify the delay, that is 2 or 3 locations to patch in a HEX file.  No disasm or asm needed. 

But that assumes that you know exactly which 2 or 3 locations to patch, and exactly how to patch them to achieve the desired effect - for which you'd either need the source code (in which case why bother), or you have to disassemble & reverse engineer it.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Now if this is code being built in Arduino (the use of the word "sketch" suggests yes) then I'm not sure how easy it is to add custom commands to the compilation step
Not very easy.  It would require modifying the Java source for the IDE and then rebuilding it (AFAIK).

 

However you can get a .lss file easily enough.  When you 'verify' or 'upload' a sketch, the results of the build are placed into a temporary directory.  On my Linux machine that's found in /tmp/build<some-random-number>/.

 

Therein you'll find a .elf file which you can pass to avr-objdump with -S.  You can do the same with the .hex file also produced.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

 

Who-me wrote:

Simpler to do what you seek, is instead to create a smart HEX editor - if you just want to modify the delay, that is 2 or 3 locations to patch in a HEX file.  No disasm or asm needed. 

 

But that assumes that you know exactly which 2 or 3 locations to patch, and exactly how to patch them to achieve the desired effect - for which you'd either need the source code (in which case why bother), or you have to disassemble & reverse engineer it.

 

No assumption needed, as this is exactly what the OP originally stated :

"I'm using the blink sketch for testing. I would like to modify the delay."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow awesome!. thanks for detailed explanation , i will give a try as soon as i can!.

Last Edited: Fri. Jun 26, 2015 - 05:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

intel .hex records have a checksum per record - edit the hex chars and you have to update the checksum accordingly