Home Upgrade Search Memberlist Extras Hacker Tools Award Goals Help Wiki Contact

How I exploited a hardcoded license to not buy software - Story

All content is for educational purposes only, information in this thread has been withheld to keep the software in question private.


The Problem
I have got a WaveShare bit of Hardware that I needed to interface with, the joys of China1 means the manual was not that much help, and logical reasoning didn't get me that far. So we're going to fast forward some level of headache, but the long and the short of it is, I am connecting a sensor to the Input side, and I want to use ModBus to query the input status, and have the Relay on the other side go High2. Back on the fact the manual wasn't much help, and not wanting to write my own ModBus communication client to just configure the hardware, I was told that we needed to purchase the software in the manual and on the website of the software in question, but of course we're on HackForums, so you should know by now that's not what I did, so let's get on with the fun times.


Reconnaissance
When you launch specific programs, you can usually tell what programming language they're made in just by their look and feel, or this could just be me. Often .NET Programs have that look and feel about that them where you move the form around and it just kinda slugs, or a C++ Program has that look like the person who wrote it went through the Win32 Message Pump hell to get it to where it is today, and looks and operates good because of it.

Introducing Windowse, in their words - "WinDowse is an extremely convenient tool for obtaining necessary technical information about any window". No this isn't the software I'm talking about, not that cheeky to drop it in casually.

This tool is actually pretty helpful to have in your Swiss Army Knife of tools, even if it is seldom used over other things. Obligatory mention of it's commercial software so ensure you abide by the license and its restrictions.

When focus on the Class Tab and hover the mouse over the target application we did get a handy little mention that tells us what de-compiler we're going to open the target in to have a poke around.

[Image: Screenshot-2025-11-24-151118.png]

Could you figure it out from that smidge of information? No? I'll give you a hint it isn't any of the numbers... Still no? Well that's okay, it's AfxWnd.
Innocuous? Yes. Revealing? Also yes. Typically VC++ and MFC use Afx as a prefix for things, so that helps a lot to tell me it is not a .NET Application, so we're going to load up Ghidra and start looking.


The Work
Ah, this is where the Pod Racing starts. First we start at the logic step first. Looking for strings relating to our Activation Message, so let's get the software to prompt us for a key, and have a look at what it tells us.

[Image: Untitled.png]

The first instance of redacting had to happen there, the application logo was on the activation screen, hopefully my awesome GIMP skills don't blind you that much, anyway...

That's a pretty standard activation screen, "Give us the Key, you get the Software". Right. Easy. Let's look in Ghidra to see if we can spot anything obvious, such as "Registration Key" as that is the title of the Box, so I'd assume there would be strings with at least "Registration" in the area, if only I knew how right I was before I got side tracked, that of course will be left out for brevity.

[Image: image.png]

Bonus Quiz moment has been cancelled, the String I am interested in is the highlighted one, this is because I'd hope there is a simple ASM instruction around the code that pushes it to the stack that is checking if the call to the activation method has passed or not.

The pseudo-code from Ghidra comes up with;
Code
iVar3 = FUN_1400874b0(&local_res10,1);
    if (iVar3 == 0) {
      pwVar7 = L"Error in the registration key";

      FUN_1400b2714(pwVar7,0x30,0);

      if (DAT_1402d4360 == '\0') goto LAB_140087dd0;
    }

That is scarily accurate to what we wanted...


Green Grass
Next time on Dragon Ball Z... Nah, I ain't going to do that to you, but I bet you were worried I was just going to leave it there saying that's what we wanted.

Let's go look into the function "0x1400874b0", and.... wait hold on? Is that a redacted license? It can't be? But the fact there is a reference to Education?

[Image: image.png]

Well before we go off and test it, why does the conditional stuff below it check for a null terminated empty string? Is that just a weird Ghidra quirk or something in this software? I am unsure, not that clever, but we'll see what it's doing before we get too excited, so we'll go look at "140087f50" as I suspect "param_2" is something passed through from the program as if it's "Activated" or some sort of message that is telling the program it needs to check the activation status ofthe program. So we might need to patch it out to ensure we're not getting nagged for an activation code again.

[Image: image.png]

Well, look at that. The spidey-sense of hindsight tingled the way we wanted! That sure looks like a timer check to see if our key is still valid!
Redacted out of this screenshot was the bit about what Registry key it opens, but it's obviously been omitted, so we'll just carry on.

Let's go check out our key in the program;

[Image: image.png]

Well fuck, all of that, and to find an educational key in the program? Probably not the first time something like this has happened, but it is one of the easier ways to activate a product without paying...


Last Call
What an odd time, finding a product key just like that off a handful of string searches, weird. But we're not done yet, we need to work out what are the quirks to this new found license that they use an expiry method.

[Image: image.png]

That's what it's in the Registry as of activation, I'll save breaking the thread up with yet another image, and just tell you.
There is a 10 day period at which this license is active, it compares the date in the Registry with what the local PC time is, and I am sure you know where the rest of this goes. We can either change the date in the Registry to be close to us, or change the Expired value from "1" to "0" then change the ACLs only allow Read but no change, then we'll never get the nag again. How good.


Foot Notes
You might wonder why some words are italics, or have a little number after them, this little section will explain some of the words I've elected to use for simplicity, or I just thought it helps flow better to allow you to flick to this to figure out later.

1: China - I acquired the WaveShare hardware through AliExpress, in this instance, I mean cheap, or as with most things from China you're usually left on your own with no technical support from a reputable company. (Or in this instance their wiki was not overly helpful to for finding what I needed.)

2: On/Active - I use this to describe a Binary Truth, it's performing the operation I expect it to, the positive outcome.


I thought I'd use this more, but apparently, I am just lazy.
[Image: 3.gif]
this is prett sick to learn
thanks will try it latter
Sure homie, you do that. I believe 100% that you can do what you set your mind to, this however, not so much.

I'll eat a snickers if anyone figures out what program it is though.
Wait who am I kidding, I'll eat a snickers anyway.
[Image: 3.gif]
Great reverse engineering, it works on some softwares with hardcoded licensing.

I have also done it in the past.
H4CK3R$ The Academy
nice to see some reverse engineering content. i have never seen anyone deduce the type of program with a window inspecting program before. i have always looked at the pe file format to check for compiler signatures or if it has .net headers and imports mscoree.dll. i think its a more reliable method if there is no gui available using your method.
Thanks for this very well written and detailed thread !

I have few questions about : in Ghidra you show the section of code that contains the temporary activation key, and the part that handles the expiry of that key.

1) How did you manage to retrieve the temporary key?
2) Did you modify the code directly in Ghidra (is that even possible?),
3) and how did you determine the location related to the expiry of the temporary activation key in the registry?

I'm not familiar at all with pseudo-code C, so I asked ChatGPT and it told me that DAT_XXXXXX elements are global data and usually contain strings / text, did you find the key there ?

[Image: image.png]

How does it work, did you click on the "DAT_1402d4368" in Ghidra and the key appeared ?

Thanks again for this thread :)
[Image: support-brown.png]
Great share. Rarely do I see content like this on reverse engineering.
Sick read man! Thanks for writing!
Very cool, I've always wanted to learn some reversing and cracking too, but there's so much other cybersecurity and programming stuff to learn and write, hard to make time. Most I've ever done is patch CRC with x64dbg for some installer I wanted to inject into.
(Nov 23, 2025 09:39 PM)6 Wrote:  Great reverse engineering, it works on some softwares with hardcoded licensing.

I have also done it in the past.
I'm glad you enjoyed it, I'll see what other things I've been up to recently to make some more

(Nov 24, 2025 03:12 AM)ttbr0 Wrote:  nice to see some reverse engineering content. i have never seen anyone deduce the type of program with a window inspecting program before. i have always looked at the pe file format to check for compiler signatures or if it has .net headers and imports mscoree.dll. i think its a more reliable method if there is no gui available using your method.
I would usually use peID I think it's called, and sometimes even just try ilspy blindly, but this day was a bit different.

(Nov 24, 2025 03:23 AM)Bastille Wrote:  Thanks for this very well written and detailed thread !

I have few questions about : in Ghidra you show the section of code that contains the temporary activation key, and the part that handles the expiry of that key.

1) How did you manage to retrieve the temporary key?
2) Did you modify the code directly in Ghidra (is that even possible?),
3) and how did you determine the location related to the expiry of the temporary activation key in the registry?

I'm not familiar at all with pseudo-code C, so I asked ChatGPT and it told me that DAT_XXXXXX elements are global data and usually contain strings / text, did you find the key there ?

[Image: image.png]

How does it work, did you click on the "DAT_1402d4368" in Ghidra and the key appeared ?

Thanks again for this thread :)
1 - it's not that strong, it's the ominous white blob, so I saw it when I searched the word registration amongst the strings.

2 - nope, no code change here, I usually use x86dbg for code changes, or if it's runtime use Microsoft detours

3 -i clicked around, and noticed there was the if statement after the use of the education key and wondered why it would check something then throw an expired warning

4 - you can double click on defined symbols like that and it should take you to where they're defined then you can see references by right clicking, though I find Ida a bit better to use for this but I didn't have it on hand at work.

Feel free to ask more questions if you'd like.

(Nov 24, 2025 05:13 AM)RangoWorld Wrote:  Great share. Rarely do I see content like this on reverse engineering.
Theanks, I'm trying to work out what else I could share but maybe with a bit more spice


(Nov 24, 2025 05:16 AM)CL1B Wrote:  Sick read man! Thanks for writing!
I'll enjoy a dart for you X

(Nov 24, 2025 10:06 AM)possessed-client Wrote:  Very cool, I've always wanted to learn some reversing and cracking too, but there's so much other cybersecurity and programming stuff to learn and write, hard to make time. Most I've ever done is patch CRC with x64dbg for some installer I wanted to inject into.
I'm happy to see a fellow employer of a good tool. I remember trying to funk with pvz and it's config, they weirdly used CRC 128 on it to ensure it wasn't tempered with
[Image: 3.gif]
(Nov 24, 2025 03:23 AM)Bastille Wrote:  I'm not familiar at all with pseudo-code C, so I asked ChatGPT and it told me that DAT_XXXXXX elements are global data and usually contain strings / text, did you find the key there ?

[Image: image.png]

How does it work, did you click on the "DAT_1402d4368" in Ghidra and the key appeared ?

Thanks again for this thread :)

it looks like this may be involved in some sort of logging function with a string to be logged and the 0x2f is the length of the string. if i had to guess, the "DAT_1402d4368" variable represents some sort of output logging object that could point to something like a file or a window that will receive the log string. i dont use ghidra but judging by the prefix of the variable, "dat" could stand for "data" which may be the data section of the pe file which would suggest a global variable. indeed there are no references to the variable in the function that i can see so there might not be any other explanation.


Possibly Related Threads...
Thread / Author Replies Views Last Post
by NeonHFDec 24, 2020 12:41 AM 6 210 Dec 24, 2020 12:41 AM
Last Post: sneezing panda
by WhokawaiApr 10, 2020 06:51 PM 1 130 Apr 10, 2020 06:51 PM
Last Post: Twistd
by trash-rootSep 2, 2019 12:48 AM 0 116 Sep 2, 2019 12:48 AM
Last Post: trash-root