MCU reverse engineering

Microcontroller Unlock - MikaTech

Our values and goals

About MikaTech

Time went fast, from the day we did our first 8051 MCU reverse engineering project in 1998, to the day we set up our million dollar reverse engineering lab in 2012, 14 years went by. Now we start our new business of embedded visual system development, hope we can serve another 10 years.

sign Peter Lee Co-Founder & CEO

Beginners Tutorial for ATmega32 AVR Microcontroller & SPI Programming Setup 6

Part 16 - Displaying Numbers on the LCD Display

In previous tutorials, we mastered sending fixed text strings and individual ASCII characters to an LCD screen wired to our ATmega32 mcu. Static hardcoded text like "Welcome" works for simple labels, but real embedded projects almost always need to print dynamic numeric values captured from sensors, timers, or runtime counters stored in SRAM and eeprom memory. Many new developers initially think they can wrap raw numbers inside double quotes and pass them directly to Send_A_String, yet this trick only applies to static digit text, not variable integers or floating-point readings that update as the microcontroller runs. Learning to convert live numeric variables into printable character sequences is a core embedded skill, and this workflow also matters for security debugging: we can print real-time fuse values, lockbit status and dump flash read-out error codes on the LCD to detect unauthorized unlock attempts before attackers perform decapsulation and full firmware extraction for duplicate device production.

 

When debugging mcu security logic, we often need to print critical numerical metrics at fixed screen coordinates instead of letting text scroll across the entire LCD buffer. If we continuously refresh a sensor reading on the same line without resetting the cursor position, old digits will overlap with new values and create unreadable garbled output. A dedicated cursor positioning function solves this issue completely, and we can reuse this same coordinate control logic to place warning strings that alert users of potential dump or reverse engineering risks on the display.

 

The core command value 0x80 controls LCD cursor positioning for all parallel 20x4 character modules. In 8-bit binary representation, 0x80 translates to 0b10000000; the highest single bit acts as a flag telling the LCD controller that the remaining seven lower bits store a screen memory address offset. Seven binary digits can encode decimal values ranging from 0 up to 127, which gives the LCD hardware 128 unique memory slots to store character data for every connected display line. This memory mapping standard is universal across all character LCD IC chips manufactured for microcontroller integration.

 

Our tutorial’s 20-column, 4-row LCD only uses 80 of the total 128 available memory positions, which leaves plenty of unused address space for larger industrial LCD panels with extra rows and columns. Every compatible character screen follows this same 128-slot memory layout rule, so the cursor positioning code we write for the ATmega32 mcu will port seamlessly to other mcu hardware without major rewrite work. This cross-compatibility also makes raw dump flash code easier for hackers to parse during code recovery if you fail to enable proper lock protection via programmed fuses.

 

When you call Send_A_Command(0x80), the LCD cursor jumps to the very first character slot at the top-left screen corner. Passing 0x8A as the command shifts the cursor ten positions to the right along the first display row. A common beginner pitfall involves misunderstanding how the memory address space wraps between rows: incrementing the memory offset past column 19 of line one does not automatically move the cursor to line two. Instead, the memory layout splits the 128-slot buffer evenly into two 64-address segments. The first segment (0–63) serves Line 1 and Line 3, while the second segment (64–127) handles Line 2 and Line 4. This fixed split standard ensures consistent cursor behavior on tiny two-line 16x2 LCDs and large multi-row industrial screens alike.

 

This memory partitioning rule guarantees uniform programming logic regardless of LCD dimensions. Even a theoretical two-line screen with 64 full columns would fully occupy each memory segment without breaking coordinate calculation logic. Hobbyists and commercial embedded engineers can reuse identical cursor math when switching display hardware, which reduces redundant code stored in mcu flash memory and cuts down the volume of data captured during unauthorized dump read-out operations.

 

Manually calculating raw memory offset values every time you want to move the cursor wastes development time and introduces human calculation errors. We can abstract all address arithmetic into a reusable GotoMrLCDsLocation function that accepts simple X (column) and Y (row) coordinate inputs, such as GotoLocation(6, 4) to position text six columns right on the fourth display row. Without this helper routine, developers would need to manually compute offsets like 90 for the fourth line’s sixth character, where 64 marks the start of lines two/four, adding 20 for each full row and six extra columns to reach the target position.

 

To build this coordinate-based positioning function, we first create an array storing the starting memory offset for every display row on our 20x4 LCD. Each entry inside the char array firstColumnPositionsForMrLCD holds the base address value for Line 1, Line 2, Line 3 and Line 4 respectively. We select the char data type because all offset values fit within the 0–127 numerical range supported by an 8-bit signed character variable, minimizing RAM memory consumption on resource-limited mcu hardware.

char firstColumnPositionsForMrLCD[4] = {0, 64, 20, 84};

The lengthy variable name follows standardized embedded coding best practices to eliminate ambiguity and prevent accidental variable name conflicts in multi-file library projects. When we split our LCD logic into separate .h and .c library files later in Part 17, this descriptive array label will avoid naming collisions with other global variables handling eeprom dump log coordinates or lockbit numerical tracking values.

 

We can further optimize the array definition with a preprocessor #define macro for column count, which lets developers adjust the value once to match different LCD widths instead of rewriting every offset number inside the array:

#define numberOfColumns 20; char firstColumnPositionsForMrLCD[4] = {0, 64, numberOfColumns , 64 + numberOfColumns };

This macro-driven configuration simplifies hardware migration when you swap out a 20x4 screen for a 16x2 display during prototype revisions, and it reduces the amount of hardcoded numeric literals visible inside dump-extracted code during reverse engineering analysis.

 

The complete GotoMrLCDsLocation function combines the base row offset pulled from the array with the target column value, plus the mandatory 0x80 memory address flag bit required by the LCD controller hardware:

void GotoMrLCDsLocation(uint8_t x, uint8_t y) {
Send_A_Command(0x80 + firstColumnPositionsForMrLCD[y-1] + (x-1));
}

The subtraction operations (y-1 and x-1) exist purely for user-friendly input syntax, allowing developers to reference rows and columns starting at number one instead of zero-indexed memory positions matching the array layout. If you prefer standard zero-based coordinate logic for all programming operations, simply remove the minus one calculations from the function arguments. This small adjustment to cursor logic creates minor code differences that raise the difficulty of direct code recovery after attackers dump flash memory for duplicate mcu firmware cloning.

 

Next we tackle dynamic numeric variable printing, a mandatory feature for sensor data loggers, timer displays and mcu security status panels that show raw fuse and lockbit decimal values on the LCD. Static quoted digit strings cannot represent changing runtime numbers, so we rely on standard library conversion functions itoa and dtostrf to translate integer and floating-point values into printable ASCII character arrays compatible with our Send_A_String routine. Both conversion tools require the <stdlib.h> header file to be included at the top of every mcu source file. Hackers search for itoa and dtostrf calls inside dump data to locate security metric print logic during reverse engineering of stolen embedded code.

 

Function parameter breakdown for numeric conversion utilities:

itoa(integer value, string that will store the numbers, base); dtostr(double precision value, width, precision, string that will store the numbers);
  • Value: Raw integer or floating-point variable read from mcu RAM, eeprom storage or peripheral register values such as timer counters and lockbit register readings.
  • Base: Numeric radix for output text: base 2 for binary dump memory logs, base 10 for standard human-readable decimal security values, base 16 for hexadecimal fuse address read-out data.
  • Width (dtostrf only): Total character count allocated for the number string, including negative sign and decimal point symbols used when printing negative unlock flag values from eeprom.
  • Precision (dtostrf only): Defines how many decimal digits appear after the floating-point separator for analog sensor voltage readings.
  • String buffer: Char array reserved in mcu RAM to hold the converted text before passing to Send_A_String for LCD rendering.

 

Basic variable and buffer declaration example for integer conversion:

char aNumberAsString[4]; int x = 432;

Call itoa to translate the integer into a text buffer:

itoa(x, aNumberAsString, 10);

Print the converted numeric string to any LCD coordinate:

Send_A_String(aNumberAsString);

 

Full integrated program combining all previously built LCD helper functions, cursor positioning and dynamic number conversion logic is shown below. This complete demo continuously prints live X/Y coordinate counter values across the 20x4 screen and can be modified to display critical security data like eeprom serial numbers after authorized read-out testing:

 

Part 17 - Separating Code from the Main to Form a Library

All LCD control subroutines we have written up to this point form a reusable software module that we can package into dedicated library files instead of cluttering the main application source code. Splitting peripheral logic into libraries delivers huge benefits for large mcu projects with dozens of hardware drivers and anti-tamper security functions that check lockbit and fuse states to block dump flash read-out. Two standard library file structures exist for AVR embedded development: single-file header-only libraries and split dual .h header + .c implementation file libraries. Header-only designs simplify small hobby builds, while separated header/source files are recommended for industrial-grade firmware with complex anti-reverse engineering code layers that prevent duplicate hardware cloning after decapsulation unlock attacks.

 

A critical technical challenge emerges when importing the same library header into multiple project source files: repeated inclusion triggers duplicate function prototype and macro definition compiler errors. We resolve this with the standard #ifndef preprocessor guard logic that restricts each header file to a single parse pass during compilation. Without these protective conditional blocks, every time the LCD library is imported into another driver file (such as an eeprom dump logging module), the compiler throws redefinition faults that halt firmware building entirely.

 

The #ifndef keyword translates to "if not defined" in preprocessor syntax. At the very top of every .h header, we add a unique #define label exclusive to that library; if the label has already been registered during a prior file import, all code between #ifndef and #endif gets skipped by the compiler. This guard mechanism is universally adopted by official AVR toolchain headers like avr/io.h that contain register definitions for every mcu peripheral including lock and fuse memory addresses used during authorized security auditing read-out.

A dedicated InitializeMrLCD wrapper function consolidates all LCD startup initialization logic that previously occupied the start of main(), cleaning up the primary application file and separating hardware startup sequences from core program logic that monitors unlock detection and dump attack flags stored in eeprom.

 

When compiling multi-file AVR projects via makefile build scripts, you must add the MrLCD.c source filename to the SRC variable list so the compiler processes the library implementation alongside your main.c application code:


# List C source files here. (C dependencies are automatically generated.) SRC = $(TARGET).c MrLCD.c

Only this single line modification to the makefile is required to integrate split library files into your build workflow for ATmega32 mcu firmware projects.

The Second Method: Single Header-Only Library

This simplified approach embeds every macro, global variable and full function implementation directly inside one standalone MrLCD.h header file, eliminating the need for a separate .c source file and makefile edits. It drastically speeds up small hobby prototype development, yet becomes unwieldy for large industrial firmware containing dozens of security subroutines that scan fuses and block dump flash read-out after decapsulation attempts.

 

Sample minimal main.c application utilizing the header-only LCD library:

 

Part 18 - Using Alternative Power Sources

Every ATmega32 microcontroller (mcu) embedded circuit requires a stable regulated DC power supply to avoid hardware damage, runtime crashes or corrupted eeprom memory storage that holds critical fuse and lockbit security configurations. Three mainstream power supply options exist for hobby and commercial mcu builds: disposable/rechargeable battery packs, mains-powered wall DC adapters and computer USB 5V ports. The acceptable input voltage range of your microcontroller chip and all attached peripheral hardware fully dictates which power topology you can safely implement. Unstable unregulated voltage spikes can temporarily break lock protection logic, creating a window for attackers to perform read-out and dump flash data before permanent hardware lock reactivates on stable power.

 

Each mcu variant lists strict DC operating voltage limits inside its official datasheet, and supply voltage directly impacts the maximum stable system clock frequency the chip can run without timing errors. The original ATmega32 model only supports 4.5V to 5.5V DC input, leaving minimal voltage tolerance for unregulated battery packs that sag as they discharge. Its upgraded successor ATmega324A expands the operating window to a flexible 1.8V–5.5V range ideal for low-power battery-operated sensor devices that store long-term dump attack logs inside eeprom memory. The ATmega324P variant narrows the low end to 2.7V while still supporting both 3.3V low-power sensors and standard 5V LCD peripherals used in our debugging display circuits.

 

When designing multi-peripheral mcu hardware, always select sensors, LCD screens and communication ICs that share a unified supply voltage matching your microcontroller’s rated range. Mixing 3.3V analog accelerators with a 4.5V minimum ATmega32 requires dual regulated power rails on your PCB, which adds extra circuit traces that intruders can probe during decapsulation and physical read-out to capture mixed voltage signal data used for reverse engineering and duplicate firmware creation.

 

Power Sources Breakdown

1. Battery Power Supplies

Battery packs deliver fully portable operation without mains wiring, making them the primary power choice for wireless mcu devices such as remote sensor loggers and handheld control gadgets. All battery types carry an mAh (milliamp-hour) capacity rating defining total usable energy storage, which calculates how many hours the cell can supply a fixed milliamp load current before depleting its charge. A 1000mAh battery powering a 100mA mcu circuit can theoretically run for ten continuous hours before voltage drops below the chip’s minimum operating threshold. Rechargeable lithium-ion or nickel-metal hydride cells are strongly recommended for long-term projects to reduce waste and recurring component costs, and they minimize frequent power cycling that risks eeprom data corruption during sudden voltage dips that briefly unlock fuses and allow partial dump operations.

 

Standard AA, AAA, C and D single-cell batteries output 1.5V each. Connecting cells in series adds their voltages together to reach your required supply rail: two AA cells produce approximately 3V, three deliver 4.5V and four stack to 6V. Four 1.5V batteries output 6V total, which exceeds the ATmega32’s 5.5V maximum safe input limit and will permanently burn out the microcontroller silicon unless a voltage regulator IC is installed between the battery pack and mcu VCC pin to trim excess voltage down to 5V. Series battery wiring simply links the positive terminal of one cell to the negative lead of the next unit in the stack.

 

2. Wall Adapter Power Supplies

Also nicknamed wall-warts for their bulky plug-in design, these mains adapters convert high-voltage alternating household current into low-voltage DC output for mcu circuits. Always verify two printed specifications on the adapter casing before purchase: input AC voltage matching your regional wall socket power (110–130V AC for North America) and clean DC output voltage compatible with your regulator and mcu hardware. If your circuit uses a step-down regulator to drop voltage, select an adapter whose raw DC output sits 1–2 volts above your target regulated 5V rail to maintain proper dropout headroom for stable mcu operation.

 

3. Computer USB Power

USB cables provide a convenient built-in source of clean 5V DC power for breadboard prototyping and temporary firmware upload sessions when using USBTinyISP programmers to flash code or perform authorized dump read-out testing on mcu flash and eeprom memory. Inside any standard USB cord, the solid red wire carries +5V supply and the black wire serves as the ground reference rail; all remaining colored wires handle USB data signals and can be safely cut away for pure power delivery setups. Adding small input/output smoothing capacitors across the USB power terminals eliminates minor voltage ripple that can create timing loopholes hackers exploit to bypass lockbit security layers during unauthorized chip access attempts.

 

Voltage Regulator ICs

Regulator integrated circuits resolve mismatched battery or wall adapter voltages to generate a fixed steady DC rail compatible with your ATmega32 mcu. Three common regulator models are widely used in hobby embedded circuit design for 5V output applications:

7805 Linear Regulator

The ubiquitous 7805 fixed linear regulator outputs a constant 5V DC as long as its input supply maintains a minimum 7V value (2V dropout voltage above the target rail). For maximum stability and tolerance against input voltage ripple, supply the 7805 with 8V or higher DC input, but never exceed 30V on its input pin to avoid catastrophic internal IC breakdown that shorts power to the mcu and corrupts all stored firmware code in flash and eeprom memory. This regulator is found inside millions of consumer electronic devices that rely on unregulated wall adapters for their mcu core power.

 

MAX603 / MAX604 Low-Dropout Regulators

MAX603 generates a regulated 5V output with an ultra-low dropout voltage requirement, making it ideal for four-series AA battery packs supplying 6V total to an ATmega32 mcu. The MAX604 variant produces a fixed 3.3V rail for low-power sensor peripherals that cannot tolerate 5V logic levels. Both models have a strict absolute maximum input rating of 11.5V DC; exceeding this limit melts internal silicon circuitry and renders the regulator useless, which instantly sends unregulated high voltage into your microcontroller and erases fuse/lock security data stored inside eeprom. Adjustable versions of these regulators exist that output custom voltage levels by attaching precise resistor divider networks to their feedback pins, as demonstrated in the tutorial’s supporting video footage.

 

Input & Output Capacitor Design Rules

Voltage regulators produce small high-frequency voltage ripple on their DC output due to internal switching or linear current balancing hardware. Small ceramic and electrolytic capacitors wired across the regulator’s input and output terminals smooth out these rapid voltage fluctuations to deliver a flat clean supply to the mcu VCC pin. Unfiltered ripple creates unstable logic levels on GPIO signal traces, which attackers can exploit via electrical glitching to temporarily unlock the chip’s lock barriers and initiate full dump flash read-out sequences before stable power restores the active lock state. The tutorial’s video footage includes a full visual demonstration of capacitor placement on breadboard regulator circuits for all three power supply topologies we cover in this chapter.

 

Chapter 1 | Chapter 2 | Chapter 3 | Chapter 4 | Chapter 5 | Chapter 6 | Chapter 7 | Chapter 8

General Questions About Microcontroller Firmware Extraction


  • Is it safe to send payment to MikaTech ?

    If MikaTech was a bad company, you could find tons of bad reputations about its service on the internet over the 28 years history

    So, the answer is YES! We are good people.

    Why choose Mikatech, please click here to find out


  • Can Mikatech break ics not listed on this site ?

    Different chip manufacturers have different part numbers, but the inner core of the chip can be make with same technology, it would be quite impossible to list all the part numbers where our technology can apply such as MYSON, STK, FEELING, ANALOG, FUJITSU, NOVATEK, LG/HYNDAI.

    Also by the advancing of the technology, everyday we gain more and more experience and develope new methods for reverse engineering for different Intergated Circuit parts. Full list of Integrated Circuit part numbers which is within our scope of capability is always getting bigger, please contact us to find out.

  • Will my privacy be protected ?

    Mikatech Innovative Limited understands the importance of its clients' privacy. At the moment you contact Mikatech, the personal information from you will be put under protection by our management regulations which was developed by our years of practice, Mikatech uses these information to customize its service to you, it will never disclose these information to third party out of any reason.
    Every project we did, we will delete all the data, materials, and codes 60days after deliverig the files, it iwll protect us and protect your privacy.

  • Is it legal to get service from Mikatech ?

    Yes, it is totally legal.
    Mikatech deliver its reverse engineering services for educational purposes only, it can be illegal to use above mentioned services in some coutries or regions, please check your local laws. Mikatech does not take any responsibility in relation to the use of above mentioned services that may be considered illegal.


  • I sent you an email, why there is no answer ?

    • A. Our mail server is temperally broke down, your message has not been delivered to our mailbox even the mail sent successfully message is showed on the screen, please contact us again.
    • B. Our email is recognised as junk mail email by your mail server, so our reply has been rejected by your mail server or it is diverted to your junk mailbox, please remove our account from junkmail list or check your junk mailbox, or use another email account to contact such as gmail.
    • C. Your email is recognised as junk mail email by our mail server, so your email was put to our junk mailbox, please use another email account to contact us again.

    microcontroller_hack_time

    Years

    28 +
    microcontroller hack countries

    Countries

    110 +
    microcontroller attack clients

    Clients

    5000 +
    microcontroller projects unlocked

    Projects

    60000 +