How I Reverse-Engineered My CPU Cooler LED Display
Tags: dotnet, reverseengineer, cpu, hacking
Published: 2024-06-17 17:36:32

> TL;DR: After a PC upgrade went sour, and made me purchase a Chinese cooler, I reverse-engineered its software to improve the accuracy of the temperature readings.

**If you're looking for the software for your Unykach AIO, you can download [Temp33 here](https://github.com/RodPaDev/temp33/releases)**

----

It all started on a hot Portuguese spring day. My new PC parts had just arrived, and I decided to upgrade my PC and give my wife the spare parts, you know, the usual move. I was upgrading from an AM4 to an AM5 socket and during my previous research, 
I found that I didn't need a new cooler, after all, I had the BeQuiet! Dark Rock Pro 4. This thing is a behemoth and appeared to be compatible since AM4 and AM5 shared mounting brackets. 

However, what they don’t share is how CPUs slot into the socket. AMD moved away from having pins on the CPU to having pins on the motherboard socket. (Yes, I am foreshadowing at this very moment. Hopefully, someone has shared this pain and knows exactly what I’m talking about.)

After 2 hours of building my PC, at the moment of truth, it didn't turn on. 

<img width="100%" style="width:100%" src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExZHkyNmVhbm4xMGlmZDYxbzl2Z3J3Y3FoN3g5MWVyNjViNm14NXQzdSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/32mC2kXYWCsg0/giphy.gif">


## Breathe. It's going to be fine.

I thought to myself, not a big deal, probably some connector loose, so I started unplugging things and nothing would work. I even spent a good hour fixated on the case connectors, used a jumper cable to short the button, and nothing. 

I took it apart and tested the power supply by jumping the relevant pins and it was working. Okay, at least something works.

I then decided to take everything apart. I took the motherboard out of the case and took out the CPU and reinserted it without the cooler. It worked! I thought to myself that it must've been the RAM or something.

## Unexpected Anger Management Classes

I built the system again and took great care in managing the cables since everything was working right? 
Well. It. Didn't. Fucking. Turn. On. At this point, I was so infuriated that wanted to buy a Komatsu D355A.

My wife told me to calm down and go for a walk to clear my head and I decided to take her advice by googling and trying different things. This was the right decision because I was so tired that I forgot to turn off the PSU when I started unscrewing the CPU cooler and THE COMPUTER TURNED ON.

<img width="100%" style="width:100%" src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExMzk5b3BteHVnMTdyMHhxNGlmMTgzMjJhdjVuajc3cW5oNm5pZzdxNyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/l3q2K5jinAlChoCLS/giphy.gif">


I screwed it in, and it turned off. The cooler which had no fans connected was controlling the power-up of the motherboard by the tension of the screws. 

It turns out that this kind of motherboard with pins (LGA) is known to have these issues. 

I decided to apply less pressure, maybe my inner mechanic was taking over since I had spent a few hours fixing my car the previous day. After unscrewing it a bit, it was working. I was tired but accepted it and decided to move on and finish the system.

## Erection Misdirection

I turned it upright, pressed the power on button, and once more... It didn't turn. 

Why, you may ask? Well, because the CPU cooler is the size of my giant balls and causes so much pressure when upright that it was bending the motherboard enough to cause problems. I found this out by lifting the cooler with a finger to ease the pressure it made.

Defeated, I decided to give up for the day, go to sleep, and tomorrow I would buy an AIO cooler, which should cause less pressure on the bracket when upright.

## The Plan B Pill
The following day I went to all the computer repair stores in my vicinity and found one AIO cooler... It was a Chinese brand called Unykach, and since I was desperate to have my daily dose of spreading democracy, I gave in and bought it. 

After installing it on the motherboard, it worked fine, CPU temps were cool and I installed the driver to display the temperature of the LED screen. I saw it change and thought _"This is cool."_. I then ran some stress tests on my PC and noticed that the temps were wildly different from every hardware monitoring software I could find. This didn't make sense, so I decided to investigate.

## Sherlock Homing
I already had some basic experience with reverse engineering software after I got frustrated with a particular enemy spawning system in `The Pirate: Caribbean Hunt` game and managed to change it. I also managed to bypass the need to purchase in-game items. 

I never shared it with anyone else and disclosed it to the developers. I can't remember if they answered or not but if they did it was so insignificant that I can't remember.

Anyway, I decided to look for DnSpy, and to my surprise, it was archived. After some googling, I found the maintained fork DnSpyEx and downloaded it. 

I proceeded then to disassemble the `.exe` file, and to my luck, it was a .NET application, more specifically it was a WPF app. 

However, to my dismay, I was looking at heavily obfuscated Chinese code. I considered giving up, but momma didn't raise no pussy (except for my brothers). So, I did what any real man would do and RTFM on how serial communication is done in `.NET`. 

Equiped with my newly acquired .NET knowledge I searched for uses of `System.IO.Ports` and perused the files like an underpaid law intern (idk I watched suits) and found the following code within the appropriately named public method `bool 品()`

```csharp
{
    DtrEnable = true,
    RtsEnable = true,
    ReadTimeout = 1000,
    BaudRate = 115200,
    DataBits = 8,
    StopBits = StopBits.One,
    Parity = Parity.None
});
base.啂().Open();
```
Written in the language of the King (not my King) this showed me exactly what I needed to be able to talk to the LED screen. It even gave me the COM port. Which I used to get the hardware instance identifier `USB35INCHIPSV2`. A quick Google search led me to this repo: [turing-smart-screen-python](https://github.com/mathoudebine/turing-smart-screen-python/wiki/Hardware-revisions). It seems that they reuse LCD firmware for 7-segment displays.

I then tried with RealTerm to send an int but to no avail. This stuff was encoded, which makes sense in retrospect, but I was hopeful.

## One Step For the Debugger, A Great Step for My Sanity

I did what any sane person would do and stepped into every statement until I found this beautiful method:

```csharp
public void 卩(int A_0, int A_1, int A_2, int A_3, int A_4, byte[] A_5 = null, int A_6 = 0)
{
    short num = (short)1832057592;
	short num2 = num;
	num = (short)1715075832;
	switch ((num2 == num) ? 1 : 0)
    ...
	try
	{
            ...
			goto IL_A0;
			IL_129:
			A_5[0] = (byte)(A_1 >> 2);
			A_5[1] = (byte)(((A_1 & 3) << 6) + (A_2 >> 4));
			A_5[2] = (byte)(((A_2 & 15) << 4) + (A_3 >> 6));
			A_5[3] = (byte)(((A_3 & 63) << 2) + (A_4 >> 8));
			A_5[4] = (byte)(A_4 & 255);
			A_5[5] = (byte)A_0;
			base.卩(A_5, true);
		}
                ...
	}
	finally
	{
        ...
	}
}
``` 

I was certain that this was the encoding method but I still had some unanswered questions: **_What do all these parameters represent? _**

When debugging with DnSpy—which, like most debuggers, displays the local variables available within the current scope. Through pattern recognition, I deduced two things: A_1 represents the integer value, and A_5 is the control or function code.


![DnSpy Execution Scope Locals](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pzkf3ud5ib4e4u9kk2n2.png)

I did this by converting the HEX values to integers and, stepping out quickly enough within the timeout window to resume the sending operation and checking the values on the physical 7-segment display.

After doing this 2-3 times I was 99% sure that A_1 was the int.

## Sanity Regained 

I then wrote a small JavaScript function that does the same encoding, ran it in the browser, and plugged the result into RealTerm, and lo and behold, I managed to send data to the LCD, and it displayed!

I tried playing around by sending 3-digit ints and it gave me cool results like reverse 7 and b and I even managed to turn on the `dot` segment.

That pretty much concludes how I managed to reverse-engineer the program.

## Dot Nettin

The rest of the time for this project was spent building a WPF app. It might be the most egregious WPF code out there, but it works and if I may say so, it looks pretty good.

![Term33 App to monitor hardware](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xnekjn4gkwk52l5sbl59.png)

You can visit the repo [here](https://github.com/RodPaDev/temp33) and if you have a problem with the `.NET` code, please send an email to: `lig@ma.balls`