{"id":66,"date":"2011-09-13T16:35:17","date_gmt":"2011-09-13T16:35:17","guid":{"rendered":"http:\/\/www.gironsec.com\/blog\/?p=66"},"modified":"2011-09-13T16:35:17","modified_gmt":"2011-09-13T16:35:17","slug":"adventures-in-keygens-part-1","status":"publish","type":"post","link":"https:\/\/www.gironsec.com\/blog\/2011\/09\/adventures-in-keygens-part-1\/","title":{"rendered":"Adventures in keygens part 1"},"content":{"rendered":"<p>Aren&#8217;t those tunes awesome? midi tracks of the 80&#8217;s packaged with a little app and shouts to people you&#8217;ve never heard of? I&#8217;m talking about keygens. And I want to go over how they&#8217;re made.<\/p>\n<p><a href=\"http:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/somekeygen.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-78\" title=\"somekeygen\" src=\"http:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/somekeygen.jpg\" alt=\"\" width=\"268\" height=\"320\" srcset=\"https:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/somekeygen.jpg 268w, https:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/somekeygen-251x300.jpg 251w\" sizes=\"(max-width: 268px) 100vw, 268px\" \/><\/a><\/p>\n<p>This is going to be a multi-parter.\u00a0 This first section is going to go over the very basics.<\/p>\n<p>&nbsp;<\/p>\n<p>For starters, most copy protection schemes today (and for the last 15 years or so) use some sort of key based authentication. The two most common bypasses for these forms of authentication are either a patch, or a generated key. A patch is when we just jump over the crap don&#8217;t like (ie; a code patch that makes consideration always true, false or not operate at all). A keygen is a program that emulates (or as will see, flat out rips off) the copy protection algorithm.<\/p>\n<p>&nbsp;<\/p>\n<p>What I have below is something I wrote recently as a keygen for a web spider application. The program is kind of stupid(although so was the copy protection scheme in place), but it works. It builds upon the simple concept that copy protection schemes are easy to copy. I&#8217;m not allowed to disclose which one since that&#8217;s against the rules (and I&#8217;m sick of the letters from my host).<\/p>\n<p>&nbsp;<\/p>\n<p>#include &lt;windows.h&gt;<br \/>\n#include &lt;stdio.h&gt;<br \/>\n#define LoWord(l) ((WORD)(l))<br \/>\n#define HiWord(l) ((WORD)(((DWORD)(l) &gt;&gt; 16) &amp; 0xFFFF)) \/\/ pelles doesnt support hi \/ lo words<br \/>\n\/\/ which just splits and shifts the double word. whatever.<br \/>\nunsigned long GenKey(DWORD);<\/p>\n<p>int main(int argc, char *argv[])<br \/>\n{<br \/>\nchar root[MAX_PATH] = &#8220;C:\\\\&#8221;;<br \/>\nchar volname[MAX_PATH];<br \/>\nDWORD serial, maxname, flags;<br \/>\nchar fsName[128];<br \/>\nDWORD fsNameLength;<br \/>\nfsNameLength = sizeof(fsName)-1;<br \/>\nGetVolumeInformation(root, volname, MAX_PATH,&amp;serial, &amp;maxname, &amp;flags, fsName, fsNameLength);<br \/>\nprintf(&#8220;Name of System: %s\\r\\n&#8221;,fsName);<br \/>\nif(volname[0] == &#8216;\\0&#8217;) \/\/ lol null<br \/>\n{<br \/>\nprintf(&#8220;No Volume name present\\r\\n&#8221;);<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\nprintf(&#8220;Volume Name: %s\\r\\n&#8221;,volname);<br \/>\n}<br \/>\nprintf(&#8220;Volume Serial Number: %x\\r\\n&#8221;,serial);<br \/>\nprintf(&#8220;Your Special key: %x\\r\\n&#8221;,GenKey(serial));<br \/>\nreturn 0;<br \/>\n}<\/p>\n<p>unsigned long GenKey(DWORD serial)<br \/>\n{<br \/>\nDWORD seed1 = 4096;<br \/>\nDWORD seed2 = HiWord(serial);<br \/>\nDWORD retme = seed1 ^ serial * seed2;<br \/>\nreturn retme;<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<p>The first 2 values displayed are topical, and made only to look nice. The last 2 are the more interesting of values. Our volume serial number assigned by NTFS(windows) when the drive is first formatted. There are 3 values that go into generating the special key value. seed1, seed2, and the volume serial number. Value one is static at 4096, the next value is the High word (that is the first 4 bytes of the double word aka the first encountered word). What is the High word of the volume serial number? Depends on the drive, but for me its 9801H or 36993 in decimal.<\/p>\n<p><a href=\"http:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/scr1.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-77\" title=\"scr1\" src=\"http:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/scr1.png\" alt=\"\" width=\"677\" height=\"359\" srcset=\"https:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/scr1.png 677w, https:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/scr1-300x159.png 300w\" sizes=\"(max-width: 677px) 100vw, 677px\" \/><\/a><\/p>\n<p>We perform an XOR (exclusive OR) on our serial number against our static value 4096. The exclusive-or operation takes two inputs and returns a 1 if either one or the other of the inputs is a 1, but not if both are. That is, if both inputs are 1 or both inputs are 0, it returns 0. So 9801D8E5 in decimal is 2550257893.<\/p>\n<p>xor 2550257893, 4096 equals 2550253797 (9801C8E5 in hex)<\/p>\n<p>Then we multiply that value against the high word of our volume serial number 9801H \/ 36993 decimal. We then shown the serial as hex via our format string specifier.<\/p>\n<p>&nbsp;<\/p>\n<p>How did I come up with this in the first place? I checked the disassembly of the protection routine. I&#8217;ll go over how to find it in the next part.<\/p>\n<p>&nbsp;<\/p>\n<p>What about the assembly? What does it look like? According to IDA:<\/p>\n<p>mov\u00a0\u00a0\u00a0\u00a0 eax, [ebp+VolumeSerialNumber]<br \/>\npush\u00a0\u00a0\u00a0 eax\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; int<br \/>\npush\u00a0\u00a0\u00a0 offset aVolumeSerialNu ; &#8220;Volume Serial Number: %x\\r\\n&#8221;<br \/>\ncall\u00a0\u00a0\u00a0 sub_401120<br \/>\nadd\u00a0\u00a0\u00a0\u00a0 esp, 8<br \/>\nmov\u00a0\u00a0\u00a0\u00a0 eax, [ebp+VolumeSerialNumber]<br \/>\npush\u00a0\u00a0\u00a0 eax<br \/>\ncall\u00a0\u00a0\u00a0 sub_4010D0<br \/>\npop\u00a0\u00a0\u00a0\u00a0 ecx<br \/>\npush\u00a0\u00a0\u00a0 eax\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ; int<br \/>\npush\u00a0\u00a0\u00a0 offset aYourSpecialKey ; &#8220;Your Special key: %x\\r\\n&#8221;<br \/>\ncall\u00a0\u00a0\u00a0 sub_401120<br \/>\nadd\u00a0\u00a0\u00a0\u00a0 esp, 8<br \/>\nxor\u00a0\u00a0\u00a0\u00a0 eax, eax<br \/>\npop\u00a0\u00a0\u00a0\u00a0 edi<br \/>\nmov\u00a0\u00a0\u00a0\u00a0 esp, ebp<br \/>\npop\u00a0\u00a0\u00a0\u00a0 ebp<br \/>\nretn<\/p>\n<p>The &#8216;protection&#8217; sub routine is made at our\u00a0 call to \u00a0\u00a0 sub_4010D0<\/p>\n<p>arg_0= dword ptr\u00a0 4<br \/>\nmov\u00a0\u00a0\u00a0\u00a0 eax, [esp+arg_0]<br \/>\nmov\u00a0\u00a0\u00a0\u00a0 edx, eax<br \/>\nshr\u00a0\u00a0\u00a0\u00a0 edx, 10h<br \/>\nmovzx\u00a0\u00a0 edx, dx<br \/>\nimul\u00a0\u00a0\u00a0 eax, edx<br \/>\nxor\u00a0\u00a0\u00a0\u00a0 eax, 1000h<br \/>\nretn<\/p>\n<p>There&#8217;s our XOR, our multiplication, ignore the right shift, that&#8217;s just compiler optimization (more on this again in the next section).<\/p>\n<p>Here is what our program looks like:<\/p>\n<p><a href=\"http:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/scr2.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-76\" title=\"scr2\" src=\"http:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/scr2.png\" alt=\"\" width=\"677\" height=\"359\" srcset=\"https:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/scr2.png 677w, https:\/\/www.gironsec.com\/blog\/wp-content\/uploads\/2011\/09\/scr2-300x159.png 300w\" sizes=\"(max-width: 677px) 100vw, 677px\" \/><\/a><\/p>\n<p>Next section &#8211; finding the algorithm in a sea of code. (Gold in a sea of piss).<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aren&#8217;t those tunes awesome? midi tracks of the 80&#8217;s packaged with a little app and shouts to people you&#8217;ve never heard of? I&#8217;m talking about keygens. And I want to go over how they&#8217;re made. This is going to be a multi-parter.\u00a0 This first section is going to go over the very basics. &nbsp; For [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4,5,6,7],"tags":[],"_links":{"self":[{"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/posts\/66"}],"collection":[{"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/comments?post=66"}],"version-history":[{"count":3,"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/posts\/66\/revisions"}],"predecessor-version":[{"id":80,"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/posts\/66\/revisions\/80"}],"wp:attachment":[{"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/media?parent=66"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/categories?post=66"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gironsec.com\/blog\/wp-json\/wp\/v2\/tags?post=66"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}