Saturday, March 20, 2021

Denuvo - I thought we were over you.

 So I wanted to play a game, it's released, it's nowhere to be found - odd I thought. I go and search online - nothing.

Surprise, surprise when I found out it has Denuvo and has gone uncracked for a long time. What happened? There was such a great track record for this and we are back to square one.

Saturday, January 9, 2021

A small boost to this creator.

 It's not often I write here, and not often I give a shout-out but a couple of weeks ago, after I contracted COVID-19 and was in quarantine, I came across a post where a person invented his own algorithm for YT recommendations and his algorithm recommended him a YT channel that youtube's algorithm would not recommend.

 It's a small channel, but deserves more views, and to better give a fighting chance for exposure of up and coming content creators versus big channels. It's not like this blog gets many views, but a boost of 1 or 2 is still a boost, right?

Hi Karolina ^^, you'll probably see this via YouTube's referrals overview. My blog is measly, but hopefully you can gain some more exposure.

Sincerely, F

Saturday, October 24, 2020

 After some cleanup I managed to get the unique code verification blocks, and narrowed them down to 35. This excludes various junk instructions inserted and different registers/memory locations. Below is the code I used to find the unique instances.

for (int i = 0; i < m.size(); i++) {
Vertex n = (Vertex) m.keySet().toArray()[i];
int size = m.get(n).size();
for (int j = 0; j < size; j++) {
Vertex v = m.get(n).get(j);

long hash = 0;
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int k = 0; k < v.insns.size(); k++) {

Instruction in = v.insns.get(k);
if(in.bytes.length == 2 && in.bytes[0] == (byte)0xEB && in.bytes[1] == (byte)0x0)



hash = ByteBuffer.wrap(md5.digest()).getInt();

if(occurrences.putIfAbsent(hash, v.insns) == null)
System.out.println("not added");
However, those 35 unique instances are variations of two operations, xor and add. So xor and add mutated to 35 unique blocks of code, multiplied a bunch of times to 22718. 

Sunday, October 11, 2020

My tool is progressing nicely.

 After a month's work I have a tool that can more or less create basic blocks from instructions.

I decided my first target, identifying and extracting all basic blocks of the little anti-bp checks of the protector.

393844C383EC 20sub esp,20
393844C6C74424 1C 406CD77Amov dword ptr ss:[esp+1C],7AD76C40
393844CEC74424 18 6E000000mov dword ptr ss:[esp+18],6E
393844D6894C24 14mov dword ptr ss:[esp+14],ecx
393844DAB9 90443839mov ecx,39384490
393844DFC14C24 1C 10ror dword ptr ss:[esp+1C],10
393844E4894424 10mov dword ptr ss:[esp+10],eax
393844E8C1E6 00shl esi,0
393844EB8B01mov eax,dword ptr ds:[ecx]
393844ED014424 1Cadd dword ptr ss:[esp+1C],eax
393844F1C1E7 00shl edi,0
393844F483C1 04add ecx,4
393844F766:FF4C24 18dec word ptr ss:[esp+18]
393844FC75 EDjne 393844EB


Just a sample of the code, the overall pattern is sub esp <size>, three movs and the most important pattern, mov reg, imm. The checks only process at most 294 bytes. And there are 22718 of them with an additional 5500 that are probably false-positives.

The next step is to analyze whether these 22k checks all use the same algorithm or are different and somehow extract it programmatically. I am exploring dataflow analysis and symbolic execution, or if the algo is the same only one sample is enough.

Saturday, September 12, 2020

I wanted to practice some Java and Python and what better way for me than writing some RE tools. I decided on my SecuROM protected executable. While I was at it I loaded up the executable in Olly and even x64dbg and to my surprise it no longer ran under a debugger. 

It took me a while to figure out that I had fiddled with Scyllahide's settings a few years back. I found out the reason it didn't work no more. A hook of NtUserFindWindowEx caused SecuROM to detect the debugger somehow, whether intentionally or it's a byproduct of something

So far, no clue but after I finish up my tooling I may find out what it is, could end up being a good anti-debug check.

Friday, September 4, 2020

There's more to programming than just the web.

It seems more and more resources and courses focus on the web and the technologies that drive the web. This can't be all there is to programming. 

I signed up for a Java course, the neat thing is I get a certified document from our Ministry of Education, but the course is all about web development. It kind of bums me out, that there are so many interesting things to solve out there, and we are churning more and more web developers.

Saturday, October 13, 2018

What is ECC(Elliptic Curve Cryptography)?

If you want to see the real math behind secp256k1 and don't want your time to be wasted reading my unfinished article, check out and for the math and as much explanation as possible.

The post title is a bit misleading as it is both a real question and a rhetorical one as well. I admit that when it comes to cryptography, I am very much in the dark.

Why though? Because cryptography requires a very solid understanding of algebra and I suppose geometry. The disambiguation of a 'curve' is literally the following on Wikipedia

curve is a geometrical object in mathematics.

And because both Algebra and Geometry fall within the broad subject of Mathematics, and because I said cryptography requires a very solid understanding of algebra, then you can infer I also mean Mathematics in general.
So you can also infer that if I am in the dark with cryptography, then I am actually pretty bad at maths.

How can someone who is bad at math, maintain a blog about reverse engineering? Well, programming in general does not always require the use of math operations more complex than a+b,a*b,a/b. On a fundamental level it's all maths, but the logic can be easy to follow.

Anyway, I set out to understand more about ECC, specifically the secp256k1 parameters which some of you might know are what power Bitcoin. Yes, it's Bitcoin that motivated me to write this post.
To be more specific it was Vanitygen, I've used the program before but the inner workings were...more mysterious and so I wanted to learn a bit more and boy is the rabbit hole deep.

Very often these 'curves' are represented as such a graph as shown below:

But then you are told that it actually looks like a scattered plot that seemingly looks random rather than the curve you see above.

In the Bitcoin wiki(not Wikipedia) has an article on secp256k1 with all the information taken from the SEC whitepaper located on

And to save you some clicks, here is what it says:

The elliptic curve domain parameters over Fp associated with a Koblitz curve secp256k1 are specified by the sextuple T = (p, a, b, G, n, h) where the finite field Fp is defined by: 
  • = 2256 - 232 - 29 - 28 - 27 - 26 - 24 - 1
The curve Ey2 = x3+ax+b over Fp is defined by:
  • a = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  • b = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000007
The base point G in compressed form is:
  • G = 02 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798
and in uncompressed form is:
  • G = 04 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798 483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8
Finally the order n of G and the cofactor are:
  • h = 01
  • secp256k1 has characteristic p, it is defined over the prime field ℤp. Some other curves in common use have characteristic 2, and are defined over a binary Galois field GF(2n)(fancy word to mean finite field), but secp256k1 is not one of them.
  • As the a constant is zero, the ax term in the curve equation is always zero, hence the curve equation becomes y2 = x3 + 7.

And finally, from OpenSSL's ec_curve.c file, we have this little structure here that defines the above data

 static const struct {  
   unsigned char data[0 + 32 * 6];  
 } _EC_SECG_PRIME_256K1 = {  
     NID_X9_62_prime_field, 0, 32, 1  
     /* no seed */  
     /* p */  
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
     0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F,  
     /* a */  
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
     /* b */  
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,  
     /* x */  
     0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95,  
     0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9,  
     0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98,  
     /* y */  
     0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc,  
     0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19,  
     0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8,  
     /* order */  
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  
     0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,  
     0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41  

Although it isn't clear what 'NID_X9_62_prime_field, 0, 32, 1' is, those are field_type, seed_len, param_len and cofactor in ec_curve.c.
Right off the bat, we can identify that we have no seed, it even says so in the description, 

My very first question looking at everything was, what the hell is G ? What is a generator 'G'? Well, if you look closely it's actually the two x and y coordinates.

The order, is apparently the maximum number of valid private keys that could be generated using this curve.

Now, there is a very basic formula posted out there on the internet is 'public key = private key * base point(which would be G)'
Cool! But not really, apparently it's not that simple. Apparently the calculation involes x,y but also a and b and p, because 'a' is 0, it's essentially omitted. More on the calculation here

I'll update the post as we try(and likely fail often) to deconstruct everything related to ECC, so until then:

to be continued...

Saturday, September 23, 2017

Binary instrumentation and recompilation of game logic to improve performance.

Fancy title, I know.

I have been interested in recompilation of game logic for specific processors for a while now.

It's probably a no brainer that games are compiled with generic compiler settings for a generic x86 processor, rather than optimizing for a specific microarchitecture(for obvious reasons).
It's also a no brainer that Intel beats AMD in performance when it comes to microarches prior to Zen. This makes a lot of old processors "useless" for gaming as games become more complex and thus require more CPU processing.

But what if you could either reduce or optimize a certain CPU intensive part of the logic so that it executes faster.

I understand that most games today might be more graphically intensive and thus require more GPU horsepower, and thus overclocking the GPU may provide more performance gain, but this won't be the case forever I think.

Battlefield 1 for PC has horrible performance, even on my i5-4670k. It requires so much CPU cycles, that the GPU is actually starved of data. DICE should fix this, but they haven't.

Monday, December 19, 2016

Been away for a while.

Over the past couple of months some major changes have happened to my life. The biggest one was the sudden passing of my father. He died in a car crash, this affected me deeply. Obviously due to this, and a sudden disinterest in RE before that made me step away for some time.

In the meantime, Denuvo was cracked, so no point in pursuing that anymore. x64dbg has progressed marvelously with ever increasing features, bug fixes and usability improvements, so I believe it has officially surpassed Ollydbg, not to mention x64 support which is the de facto standard these days.

Tuesday, July 5, 2016

Useless post.

Going to dig in a bit. Presumably what I am looking at is the Origin DRM, so what I am looking at is not Denuvo. And yes, that is a (useless) screenshot of the first thing I see when I load up an Origin game in x64dbg. So it's nothing special.

Quite frankly, I am angry, the shitposting on reddit regarding Denuvo, the false promises, the contradicting information of what Denuvo does, how it works etc.
How about I post what I find in addition to screenshots(or videos?) that at least proves/disproves something or sheds some light on the functionality.