• No results found

4.pdf

N/A
N/A
Protected

Academic year: 2020

Share "4.pdf"

Copied!
6
0
0

Loading.... (view fulltext now)

Full text

(1)

1.

Analysis

Hi guys!

Well, it’s time to keygen a game, isn’t it? Today we’re going to defeat Waga Invader by Waganono. I’ve to say Waganono had an original idea, this game is simple but funny and the crypto protection scheme is really good even if in the last few years it isn't too much used.

Before we start I’ve to said THANKS to Shub-Niggurath and the whole ARTeam, they allowed me to use their template, Waganono for this challenge and for his hints and to jB who helped, supported and lost his free time (and I think also a good part of his patience!) for me.

This game was coded in C with OpenGL (for the game) and Miracl (for the algorithm) so I used a little bit IDA, its signature windows and the miracl.sig (you can find it here: http://beatrix2004.free.fr/pamplemousse/miracl.sig). I wrote “a little bit” in fact it doesn’t recognize many functions but no problem, playing a lot with Miracl I know exactly which are the other unknown functions. Always in IDA you can export the .map file (as I did) and with Olly’s plugins like LoadMap or GODUP you can import this .map file and see the name of all known calls directly in Olly. I’ve modified my .map file with all interested function’s names.

Then… Open it with Olly and search for all referenced text strings until you see something like:

Figure n.1 – Text strings

Hum…

What do you think? Are you thinking RSA, right? Let’s check it out, double left click over the long number and we are exactly in the middle of the algorithm! Bingo! Now load my .map file, in this way you can better understand the algorithm.

>DISASSEMBLY

004036C0 push 10 ; 0x10 = 16 004036C2 push 12C ; 0x12c = 300 004036C7 mov byte ptr ss:[esp+1F],1

004036CC call <wagainva._mirsys> ; init miracl with 300 hexadecimal digits for each big 004036D1 push 0 ; mirvar’s parameter, describes the initial value of big 004036D3 mov dword ptr ds:[eax+230],10 ; hexadecimal base

004036DD call <wagainva._mirvar> ; initialises a big variable

004036E2 push 0 ; mirvar’s parameter, describes the initial value of big 004036E4 mov dword ptr ss:[esp+30],eax ; save the pointer to the reserved memory after mirvar 004036E8 call <wagainva._mirvar> ; initialises a big variable

004036ED push 0 ; mirvar’s parameter, describes the initial value of big 004036EF mov dword ptr ss:[esp+30],eax ; save the pointer to the reserved memory after mirvar 004036F3 call <wagainva._mirvar> ; initialises a big variable

004036F8 push 0 ; mirvar’s parameter, describes the initial value of big 004036FA mov dword ptr ss:[esp+3C],eax ; save the pointer to the reserved memory after mirvar 004036FE call <wagainva._mirvar> ; initialises a big variable

00403703 push 0 ; mirvar’s parameter, describes the initial value of big 00403705 mov ebx, eax ; copy the pointer of a new big into ebx

00403707 call <wagainva._mirvar> ; initialises a big variable

0040370C push 0 ; mirvar’s parameter, describes the initial value of big 0040370E mov dword ptr ss:[esp+38],eax ; save the pointer to the reserved memory after mirvar 00403712 call <wagainva._mirvar> ; initialises a big variable

Diasm n.1

W

W

a

a

g

g

a

a

I

I

n

n

v

v

a

a

d

d

e

e

r

r

b

b

y

y

W

W

a

a

g

g

a

a

n

n

o

o

n

n

o

o

O

OXX8877KK 2

(2)

PAGE 2 WAGA INVADER BY WAGANONO

As we can see in this piece of code there is a mirsys call and after many mirvar. The algorithm is already started, it initialises the MIRACL system and after that it allocates memory for six big numbers initialized to zero.

The C code is something like this:

>C CODE

#include "lib\miracl.h"

void Serial_Check(char *serial) {

miracl *mip; // Init MIRACL

mip = mirsys(300, 16); // 300 hexadecimal digits for each bignum mip->IOBASE = 16; // Hexadecimal base for all operations

big s = mirvar(0); // Allocate memory for a bignum initialized to zero big n = mirvar(0); // Allocate memory for a bignum initialized to zero big k = mirvar(0); // Allocate memory for a bignum initialized to zero big h = mirvar(0); // Allocate memory for a bignum initialized to zero big e = mirvar(0); // Allocate memory for a bignum initialized to zero big x = mirvar(0); // Allocate memory for a bignum initialized to zero

Code n.1

Until now it’s not too hard to understand, yep? Continue with the analysis of the algorithm.

>DISASSEMBLY

0040371A push wagainva.0042F284 ; /string = "GAGANONO" 0040371F mov ebp,eax ; |

00403721 call dword ptr ds:[<&kernel32.lstrlena>] ; \lstrlena -> GAGANONO, how long is it? lol! 00403727 mov edi,eax ; len(GAGANONO) = 8 chars and save it in edi 00403729 lea eax,dword ptr ss:[esp+28] ; eax points to an instance of sha256 struct 0040372D push eax ; push this structure as parameter

0040372E call <wagainva._shs256_init> ; initialises an instance of SHA-256 00403733 add esp,4

00403736 xor esi,esi ; esi = 0 (reset the counter) 00403738 test edi,edi ; len(GAGANONO) != 0

0040373A je short <wagainva.loc_40375C> ; yes so don’t jump away and continue 0040373C lea esp,dword ptr ss:[esp]

00403740 movsx eax,byte ptr ds:[esi+42F284] ; al = string_GAGANONO[esi] 00403747 push eax ; push the char

00403748 lea ecx,dword ptr ss:[esp+2C] ; ecx points to own instance of sha256 0040374C push ecx ; push this struct

0040374D call <wagainva._shs256_process> ; processes a single byte 00403752 add esi,1 ; esi += 1 (counter++) 00403755 add esp,8

00403758 cmp esi,edi ; counter == len(GAGANONO) ? if yes

0040375A jnz short <wagainva.loc_403740> ; go out else jump to process another char 0040375C lea edx,dword ptr ss:[esp+28] ; edx points to own struct processed before 00403760 push wagainva.00430514 ; push a string at least 32 chars

00403765 push edx ; push own struct processed

00403766 call <wagainva._shs256_hash> ; generates a 32 byte hash into this string 0040376B add esp,8

0040376E xor esi,esi ; esi = 0 (reset the counter) 00403770 mov edi,wagainva.004304D0 ; edi points to another empty string 00403775 jmp short <wagainva.loc_403780>

00403777 lea esp,dword ptr ss:[esp]

0040377E mov edi,edi ; EHI, LOOK AT THAT SHIT! <- =) 00403780 movzx eax,byte ptr ds:[esi+430514] ; al = sha256_string_result[esi] 00403787 push eax ; /<%02x>

00403788 push wagainva.00428DCC ; |format = "%02x" 0040378D push edi ; |s

0040378E call dword ptr ds:[<&user32.wsprintfa>] ; \wsprintfa

00403794 add esi,1 ; esi += 1 (counter++) 00403797 add esp,0C

(3)

PAGE 3 WAGA INVADER BY WAGANONO

Nothing hard just gets the string “GAGANONO” and generates its SHA-256 hash. After that it converts each byte for 28 times (and not 32) so the result is:

Input String GAGANONO

Length 8

Waga Invader’s SHA-256 9D762D2018E010104148CCB6ED4B2A23B826CA97C3DB374B564CF901

Original SHA-256 9D762D2018E010104148CCB6ED4B2A23B826CA97C3DB374B564CF9018D456B88

So the code would be something like:

>C CODE

…… previous code ……

#define waga_str "GAGANONO"

char hash[100]; // String for SHA-256 final output BYTE digest[32]; // Array of 32 bytes

sha256 psh; // Instance of sha256 structure

shs256_init(&psh) ; // Initialises this instance // Processes each single byte

for(i=0;i<strlen(waga_str);i++) {

shs256_process(&psh, waga_str[i]); }

// Generates the 32 byte hash shs256_hash(&psh, digest);

// Print out the SHA-256 (28 chars) into the string called “hash”

for(i=0;i<28;i++) {

wsprintf(hash+(i*2), "%02X", digest[i]); }

Code n.2

Good, another piece of code..

>DISASSEMBLY

004037A2 mov ecx,dword ptr ss:[esp+18] ; ecx points to a bignum 004037A6 push wagainva.00430538 ; ascii "123456789012345678901234567890" <- own serial 004037AB push ecx ; push the address of a bignum

004037AC call <wagainva._cinstr> ; inputs a bignum from a character string 004037B1 mov edi,dword ptr ss:[esp+28] ; edi points to another bignum

004037B5 push wagainva.0042F208 ; ascii "26A1768C0DAB078115BCA03C5ECFC39EBE7FEC84478D7B3CFC0D6E3A6A3555AC08DB" 004037BA push edi ; push the address of a bignum

004037BB call <wagainva._cinstr> ; inputs a bignum from a character string 004037C0 mov edx,dword ptr ss:[esp+2C] ; edx points to another bignum 004037C4 push wagainva.0042F250 ; ascii "29A"

004037C9 push edx ; push the address of a bignum

004037CA call <wagainva._cinstr> ; inputs a bignum from a character string 004037CF push wagainva.004304D0 ; ascii "9D762D2018E010104148CCB6ED4B2A23B826CA97C3DB374B564CF901" 004037D4 push ebx ; push the address of a bignum

004037D5 call <wagainva._cinstr> ; inputs a bignum from a character string 004037DA push wagainva.0042F254 ; ascii "1000000000000000000000000000000000000000000000"

004037DF push ebp ; push the address of a bignum

004037E0 call <wagainva._cinstr> ; inputs a bignum from a character string

Diasm n.3

(4)

PAGE 4 WAGA INVADER BY WAGANONO

>C CODE

…… previous code ……

cinstr(s, serial); // Converts into a bignum own serial cinstr(k, "29A");

cinstr(n, "26A1768C0DAB078115BCA03C5ECFC39EBE7FEC84478D7B3CFC0D6E3A6A3555AC08DB"); cinstr(h, hash); // Converts into a bignum the hash of GAGANONO cinstr(e, "1000000000000000000000000000000000000000000000");

Code n.3

It’s time to understand something!

>DISASSEMBLY

004037E5 mov esi,dword ptr ss:[esp+4C] ; esi points to an empty bignum (x) 004037E9 mov eax,dword ptr ss:[esp+44] ; eax points to bignum k

004037ED mov ecx,dword ptr ss:[esp+40] ; ecx points to bignum s (own serial) 004037F1 push esi ; push bignum x

004037F2 push edi ; push bignum n (edi points to n) 004037F3 push eax ; push bignum k

004037F4 push ecx ; push bignum s (own serial) 004037F5 call <wagainva._powmod> ; x = (s**k) % n

004037FA push ebp ; push bignum e (ebp points to e) 004037FB push ebx ; push bignum h (the SHA-256 hash) 004037FC push ebp ; push bignum e (another time) 004037FD call <wagainva._add> ; e = e + h

00403802 add esp,44

00403805 push esi ; push the bignum x (result of powmod) 00403806 push ebx ; push the bignum h (the SHA-256 hash) 00403807 call <wagainva._compare> ; compare h and x

0040380C add esp,8

0040380F cmp eax,1 ; if the result of compare isn’t 1 then jump 00403812 jnz short <wagainva.loc_403819> ; to the next compare else it doesn’t jump and 00403814 mov byte ptr ss:[esp+17],0 ; set this byte to zero

00403819 push ebp ; push the bignum e

0040381A push esi ; push the bignum x (result of powmod) 0040381B call <wagainva._compare> ; compare x and e

00403820 add esp,8

00403823 cmp eax,1 ; if the result of compare isn’t 1 then jump 00403826 jnz short <wagainva.loc_40382D> ; out else it doesn’t jump

00403828 mov byte ptr ss:[esp+17],0 ; and set the same byte as before to zero

Diasm n.4

Well, the core of the algorithm is all here. We have a powmod, an add and two compare. With the powmod it raise a big number to a big power modulus another big number. In this case we have:

x = sk mod n

|

= (serial**0x29A) % 26A1768C0DAB078115BCA03C5ECFC39EBE7FEC84478D7B3CFC0D6E3A6A3555AC08DB

Next step, the add. It adds a bignum (represented in this case from ‘e’) to another bignum (‘h’, the hash). As serial I tried “123456789012345678901234567890” and now my situation is this:

x (result of powmod) 1615A79B496E78184D33547E749ADCD640115BC2C5CC59276ACAC1F4C129A02B56D0 e 1000000000000000000000000000000000000000000000

h 9D762D2018E010104148CCB6ED4B2A23B826CA97C3DB374B564CF901 e after the add 9D762D2018F010104148CCB6ED4B2A23B826CA97C3DB374B564CF901

Result’s table n.1

(5)

PAGE 5 WAGA INVADER BY WAGANONO

The compare(x, y) function returns 1 if x>y, returns 0 if x==y and returns -1if x<y. In the two cases the returned value must be NOT equal to 1 because if one of two compare returns back 1 then own tested byte will be zero while at the beginning own byte isn’t zero and we need this variable not equal to zero.

At the first compare we have compare(h, x) so the parameter ‘x’ will be own bignum ‘h’ while the parameter ‘y’ will be own bignum ‘x’. As I told you before, we need a returned value not equal to 1 and it can be possible only if parameter x is <= than parameter y. In this case it’s true because bignum x is greater than bignum h (look at table called Result’s Table n.1).

At the second compare we have compare(x, e) so the parameter ‘x’ will be own bignum ‘x’ while the parameter ‘y’ will be own bignum ‘e’. As I told you before, we need a returned value not equal to 1 and it can be possible only if parameter x is <= than parameter y. In this case it’s false because this time bignum x (after the add) is greater than bignum e (look at table called Result’s Table n.1) while we need it less big than e (always after the add).

Finally we need a result of powmod like this:

9D762D2018E010104148CCB6ED4B2A23B826CA97C3DB374B564CF901 <= x <= 9D762D2018F010104148CCB6ED4B2A23B826CA97C3DB374B564CF901

The final code with the last functions is the following

>C CODE

…… previous code ……

powmod(s,k,n,x); // x = (s**k) % n

add(e,h,e); // e = e + h

if(compare(h,x)!=1 && compare(x,e)!=1) // if x>=h AND x<=e

isRight=TRUE; // WELL DONE! We've found a valid serial

mirkill(x); // Kills off a bignum by zeroising it and freeing its memory mirkill(n); // Kills off a bignum by zeroising it and freeing its memory mirkill(k); // Kills off a bignum by zeroising it and freeing its memory mirkill(s); // Kills off a bignum by zeroising it and freeing its memory mirkill(h); // Kills off a bignum by zeroising it and freeing its memory mirkill(e); // Kills off a bignum by zeroising it and freeing its memory

mirexit(); // Cleans up and frees all internal variables

Code n.4

Too easy until now.. In fact try to factorize N with RSA Tool or Msieve and look!!! Own N isn’t composed by two prime numbers or better yes but the formula isn’t the classic N = p*q but another.

N (270 bits) 26A1768C0DAB078115BCA03C5ECFC39EBE7FEC84478D7B3CFC0D6E3A6A3555AC08DB

p1 3755CA6CDD6B49826A669A3

p2 3755CA6CDD6B49826A669A3

q 33AD1EAA125E7B119B6F383

So the classic formula becomes N = p*p*q or better N = (p**2) * q.

Never heard before now of this kind of algorithm and then Waganono gave me an hint. All doubts can be defeat by this link: http://www.codeproject.com/useritems/ESIGN.asp

It’s ESIGN!

Easy to understand the following. The three steps to Key generation are outlined below. The Public Key is (n, k) and the Private Key is (p, q).

1) Select primes p and q of roughly the same bitlength with p >= q 2) Compute N = p2q

(6)

PAGE 6 WAGA INVADER BY WAGANONO

All is confirmed from the fact that all we saw is just the ESIGN’s Signature Algorithm.

1) Compute v = sk mod n (in this case we have x = sk mod n)

2) Compute z = h(m) (in this case we have h = SHA-256(“GAGANONO”))

If z <= v <= z + 2CEIL( (2/3) lg n ), the signature is valid. Otherwise, reject the signature.

So in order to code a valid keygen we need to follow this scheme:

1) d = H(m) (in this case for us d will be own h (the hash))

2) Select a random integer x such that 0 < x < p 3) Compute w = CEIL( (( d - xk) mod n ) / (p*q) )

4) Compute y = w * (k * xk-1)-1 mod p

5) Compute s = x + y*p*q mod n

In step three, w is simply the least integer that is larger than or equal to ( H(m) - xk mod n ) / p*q.

For other information look the source (it’s commented) of my keygen! Sorry for the bad code but it was the first time for me that i saw ESIGN.

For today is all, game over! Sorry for my bad English, hope you could understand me. Ciao! ;-)

2.

References

Ø Applied Crypto++: Using the ESIGN Digital Signature System by Jeffrey Walton

(http://www.codeproject.com/useritems/ESIGN.asp/)

Ø Self-Evaluation of ESIGN Signatures

(http://mack.ittc.ku.edu/cache/papers/cs/17310/http:zSzzSzwww.crypto.nkfu.edu.twzSzCRYPTOzSzSelf_ESIGN.pdf/self-evaluation.pdf/)

Ø M.I.R.A.C.L

(http://www.shamus.ie/)

Ø Handbook of Applied Cryptography by A. Menezes, P. van Oorschot, S. Vanstone

(http://www.cacr.math.uwaterloo.ca/hac/)

Ø ARTeam

(http://arteam.accessroot.com/)

Ø jB’s web space

(http://jardinezchezjb.free.fr/)

3.

Greetings

Thanks Waganono for this original keygenme! Thanks all TEAM ICU, ARTeam, REVENGE, SnD

Thanks Shub-Nigurrath, Zairon, black-eye, CuTedEvil ;)

Thanks Ank83, Guetta, HMX0101, deroko, haggar, ++Meat, x15or, all crackmes.de community Thanks UIC (università italiana cracking - www.quequero.org)

Thanks ThunderPwr, SatUrN, Quequero, AndreaGeddon, active85k, Zero_G, Pn[L]uck, Death-Reaver, theANGEL, n00b, and etc... :D

Figure

Figure n.1 – Text strings
table called Result’s Table n.1).   At the second compare we have

References

Related documents

Title Regiospecificities and Prenylation Mode Specificities of the Fungal Indole Diterpene Prenyltransferases AtmD and PaxD.. Author(s) Liu, Chengwei; Minami, Atsushi; Noike,

This act of nepotism contributes to the high rate of illiteracy by causing people not to go to school because they believe that even if they get educated, they

If a student repeats a course, all grades for the course are calculated into the GPA and listed on the academic record; however, only the course earning the first passing grade

and in our simple example in the text above of a filters lower and upper -3dB cut-off points being at 200Hz and 600Hz respectively, then the resonant center frequency of the active

Abbreviations: AAV2, adeno-associated virus 2; AcMNPV, Autographa californica multiple-capsid nucleopolyhedrovirus; cNLS, classical nuclear localization sequence; cPPT,

Regarding the product specific characteristics the properties of the various categories of functional foods (i.e. health-enhancing, feel good and sport functional foods)

Following UBC’s Place and Promise commitment to provide a broad scope of continuing studies programs to support students and life-long learners , and in response to strong

Plan Steps Responsible Parties Target Date/Timeline Resources ($, people) Indicators of Success /Notes. Progress Report (date)_________ A1- Provide training IT staff /