1-1-3-5-15 这段代码是什么意思啊?
发信人: FrankCH (终有绿叶衬), 信区: Java标题: Re: 这段代码是什么意思啊?
发信站: BBS 水木清华站 (Wed Jul3 17:38:34 2002)
【 在 FrankCH (终有绿叶衬) 的大作中提到: 】
: 嘿嘿,这块石头好眼熟啊。。
嘿嘿。。
我贴一段东西大家看看吧。想玩java decode的都该看看的
$Revision: 1.1 $
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Cracking Zelix KlassMaster's String Encryption
(and how to get hiscores in Java games)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
by Morten Poulsen
m0rtenp@ofir.dk
http://www.zelix.com/klassmaster/featuresStringEncryption.html
"However, note that Zelix KlassMaster's String Encryption isn't and
cannot be fundamentally irreversible."
Introduction
~~~~~~~~~~~~
To make decompilation of Java applets and making changes to the code more
difficult, and to hide secret information (eg. how to calculate hashes for
hiscores) people obfuscate their java bytecode. Some of the ways to do so is
to scramble the line number tables, replace all names of classes, methods an
d
variables with nonsense, and the one we will look at, string encryption.
You will need a few tools to help you do the job:
- Java decompiler (Jad)
- editor (vim)
- common sense (brain)
some knowlage about JVMs will be nice, but I tell you everything you need to
know here. If you want to make your own cracks, you need that knowlage.
Some tools are nice to have when cracking the hiscore tables of Java games:
- TCP sniffer (tcpdump)
- "Java enabled" browser (Mozilla)
- C compiler (gcc)
- all the GNU tools (eg. grep)
- webserver with PHP ;-)
What's going on?
~~~~~~~~~~~~~~~~
Forst of all we need to find a game to crack. The games on Coca~Cola's
(nordic) website looks like great candidates. Start the TCP sniffer (tcpdump
-w file), and launch the game. Play the game and write down your score. Stop
the TCP sniffer, and open the file (vi file). Search for your score in the
binary masses. You shuld find a line a'la:
GET /magazine/servlet/SetHighscoreServlet?score=6324&game=0&cookie=yourname&
md5=c404cd019e1a214487cd4c841
So all we need to know is how to generate the md5 hash, then we will be able
to make our own hiscores, hopefully.
Decompiling and Thinking
~~~~~~~~~~~~~~~~~~~~~~~~
Download the .jar archive containing the game (hint: view source, <applet
>
tag, archive=...), unpack it and decompile each class. Now try to find the
place in the code where the result is send back to the server (fgrep -rn "UR
L"
*). b/a/a.java line 122 (decompiled with jad) looks like a god place to star
t.
It reads:
URL url = new URL(c, b("L9\001 qMdK|)\016rZ!\f\007cfg8\ndMa-\007DK|)
\016rZ1,\001x\\kb") + Integer.toString(i) + b("DpOc:_") + d + b("DtA
a4\013r\023") + e + b("DzJ;b") + a.a.a.a.a.a(i, Integer.parseInt(d), e))
;
The URL looks a lot like what we seek:
"long text"+i+"text"+d+"text"+e+"text"+result_of_calculation(i,d,e)
the problems are now "are these strings the ones we seek?" (just for the fun
of it - lets find out) and "what does a.a.a.a.a.a() do?".
Open the file (vi b/a/a.java) and seek to line 122. We can see that the
method used to decrypt the string is b(). Seek to b() (line 224). It looks
like this:
224: private static String b(String s)
225: {
226: char ac[];
227: int i;
228: int j;
229: ac = s.toCharArray();
230: i = ac.length;
231: j = 0;
232: goto _L1
233: _L9:
234: ac;
235: j;
236: JVM INSTR dup2 ;
237: JVM INSTR caload ;
238: j % 5;
239: JVM INSTR tableswitch 0 3: default 76
240: // 0 52
241: // 1 58
242: // 2 64
243: // 3 70;
244: goto _L2 _L3 _L4 _L5 _L6
245: _L3:
246: 0x62;
247: goto _L7
248: _L4:
249: 23;
250: goto _L7
251: _L5:
252: 46;
253: goto _L7
254: _L6:
255: 14;
256: goto _L7
257: _L2:
258: 95;
259: _L7:
260: JVM INSTR ixor ;
261: (char);
262: JVM INSTR castore ;
263: j++;
264: _L1:
265: if(j < i) goto _L9; else goto _L8
266: _L8:
267: return new String(ac);
268: }
Java's Virtual Machine is a stack based machine. That is, there is only o
ne
register, the instruction pointer, the rest of what registers are normaly us
ed
for is done on the stack. Example: c=a+b is done PUSH a, PUSH b, ADD (which
pop the operands off the stack, and push the result back), POP c.
If we look closer at the code, we can see that the lines 232,233,264,265,
266 are just a while-loop, looping through the chars in the string. Line 238
pushes the result of j (the index into the string) modulus 5 on the stack.
Lines 239-259 looks like a switch/case, pushing a nubmer onto the stack, bas
ed
on j%5. Line 260 pops two operands off the stack - a char from the encrypted
string, and the mysterious number, and pushes back the result of an XOR. Ah!
The mysterious numbers are the key of a simple XOR encryption! Written in C
it
would look like:
for (j=0; j<strlen(str); j++) {
str ^= key;
}
that's it. Just a plain 40-bit XOR. Let's make a short program to decrypt a
string. I am lazy so everything is hard-coded.
decode1.c:
----------------------------------------------------------------------------
--
#include <stdlib.h>
#define KEYSIZE 5
int main(void) {
unsigned char buf[] = "L9\001 qMdK|)\016rZ!\f\007cfg8\ndMa-\007DK|)\016r
Z1,\001x\\kb";
unsigned char key1[] = { 0x62, 23, 46, 14, 95 };
unsigned char c;
int i;
for (i=0; i<strlen(buf); i++) {
c = buf ^ key1;
printf("%c", c);
}
printf("\n");
return EXIT_SUCCESS;
}
----------------------------------------------------------------------------
--
weeee, running it (gcc decode1.c && ./a.out) returns:
../../servlet/SetHighscoreServlet?score=
so this was all that had to be done! A few lines of C, and the strings can b
e
decrypted.
The Hash Function
~~~~~~~~~~~~~~~~~
The hash in the HTTP-request looks a lot like an MD5, and the name in the
URL is "md5", so my guess is: It's an md5 of the score, the game id, the
username and some secret string. But why does the method take three paramete
rs
(long,int,String)? That's not normal for MD5 functions. Open the file (vi
a/a/a/a/a.java) and seek to the version of a() taking the three parameters
(line 83). Ah! It calls the real MD5 method with a string:
(l + i) + s + "some secret string"
where l is the score, i is the gameid and s is the username. But the secret
string is encrypted. Actualy it is encrypted two times (see, it calls both c
()
and b()), but that shuld be no problem at all.
Seek to method c() (line 140). Ha! It's just like the other one, only the
key is changed. Let's have a look at methos b() (line 89). Haha, the same
thing here. So all we need to do to get the secret string is to change a few
lines in the decode program so it can handle two keys.
decode2.c:
----------------------------------------------------------------------------
--
#include <stdlib.h>
#define KEYSIZE 5
#define BUFSIZE 25 /* needed, 'cause buf has a null byte */
int main(void) {
unsigned char buf[] = "mS?\032<lD/\0137aS&\003<e_,\013*}D.\000>";
unsigned char key1[] = { 0x71, 103, 47, 41, 9 };
unsigned char key2[] = { 120, 81, 100, 71, 80 };
unsigned char c;
int i;
for (i=0; i<BUFSIZE; i++) {
c = buf ^ key1 ^ key2;
printf("%c", c);
}
printf("\n");
return EXIT_SUCCESS;
}
----------------------------------------------------------------------------
--
running the program gives us the result "detteerdenhemmeligestreng" which is
danish for "thisisthesecretstring". ROFL.
Exploiting the Hiscore
~~~~~~~~~~~~~~~~~~~~~~
WARNING! Don't try this at home, you will just get into trouble ;-)
I am lazy, so I wrote a little PHP script to generate the URL's to request
from the server to set hiscores (eg. just copy/paste into browser). Try it t
o
see if the hash is the same as the one you got playing the game (no, my hash
here is fake, use your own).
hash.php:
----------------------------------------------------------------------------
--
<html>
<head>
<title>Coca~Cola hiscore generator</title>
</head>
<body>
<?php
if ($cookie) print("http://www.coca-cola.fi/magazine/servlet/SetHighsc
oreServlet?score=$score&game=$game&cookie=$cookie&md5=".md5($score.$cookie.'
detteerdenhemmeligestreng')."<br>\n");
print("<form>\n");
print("<input type=\"text\" name=\"score\" value=\"" . (int)$score . "
\" size=\"10\"><br>\n");
print("<input type=\"text\" name=\"game\" value=\"" . (int)$game . "\"
size=\"2\"><br>\n");
print("<input type=\"text\" name=\"cookie\" value=\"$cookie\" size=\"3
0\"<br>\n");
print("<input type=\"submit\" value=\"go go go\">\n");
print("</form>");
?>
</body>
</html>
----------------------------------------------------------------------------
--
页:
[1]