- Joined
- Feb 22, 2008
- Messages
- 2,404
- Reaction score
- 724
So it would be only possible to reverse strings when dir would be inside a range of 33 (e.g. 0-32 or 97 - 129) and EDX does not overflow.
So, if you could assume that the string only has minuscles (which are ascii 97-122, it might be possible:
This can be further improved by bringing ch into other ranges of the ascii range (e.g. numbers, uppercase letters) if you feel, that the calculated char is incorrect. But this makes the algorithm heuristic then.
- First, subtract 0x1505 from VAL
- Then, calculate ch = VAL % 33
- Calculate ch = ch + n*33. Choose n in a way to get ch into the range 97-129, this is the next char.
- Subtract this char from VAL and divide by 33: VAL = (VAL - ch) / 33
- Iterate from step 2 until VAL is 0.
<?php
/*
int EDI = 0x1505;
for( int i = 0; i < lstrlen(dir); i++ )
{
if ( dir[i] != '.' && dir[i] != '\' )
{
EDX = EDI * 32;
EDX = EDX + EDI;
EDX = EDX + dir[i];
EDI = EDX;
}
}
*/
$dir = 'test\data';
$EDI = 0x1505;
for ($i = 0; $i < strlen($dir); $i++) // STRLEN
{
if ($dir[$i] != '.' && $dir[$i] != '\\')
{
$a = $EDI * 32;
$b = $a + $EDI;
$c = $b + ord($dir[$i]);
$EDI = $c;
}
}
echo 'result: ' . $EDI . PHP_EOL;
$value = $EDI;
//$value = 2520255578;
$result = '';
while ($value > 0x1505)
{
$ch = $value % 33;
while ($ch < 97)
{
$ch += 33;
}
if ($ch > 129)
{
echo 'Data failure ' . $ch . PHP_EOL;
exit;
}
$value = floor(($value - $ch) / 33);
$result .= chr($ch);
}
$result = strrev($result);
echo $result . PHP_EOL;
unsigned int __fastcall sub_4547A0(int a1, const char *a2)
{
unsigned int v2; // edi@1
unsigned int v3; // esi@1
unsigned int v4; // kr00_4@1
int i; // ecx@1
char v6; // al@2
unsigned int v7; // ecx@6
char v8; // al@7
char Dst[0x400];
v2 = strlen(a2);
v3 = 5381;
strcpy_s(Dst, 0x400u, a2);
v4 = strlen(Dst);
for (i = 0; i < (signed int)(v4 + 1); ++i)
{
v6 = *(Dst + i);
if (v6 >= 65 && v6 <= 90)
*(Dst + i) = v6 + 32;
}
v7 = 0;
if (v2)
{
do
{
v8 = *(Dst + v7);
if (v8 != 46 && v8 != 92)
v3 = v8 + 33 * v3;
++v7;
} while (v7 < v2);
}
memset(&Dst, 0, 0x400u);
return v3;
}
char dir[] = "data\\map\\realworld_r\\01_yokohama\\105\\map_data\\105.emr";
unsigned int values = sub_4547A0(1, dir);
v8 = *(Dst + v7);
if (v8 != 46 && v8 != 92)
v3 = v8 + 33 * v3;
d = 100
a = 97
t = 116
a = 97
result = 5381
result (177673) = d (100) + 33 * result (5381)
result (5863306) = a (97) + 33 * result (177673)
result (193489214) = t (116) + 33 * result (5863306)
result (6385144159) = a (97) + 33 * result (193489214)
result (6.385.144.159) > 2.520.255.578
Well, the number got overflow and the steps are continued. The "formula" dont care about the overflow, so you cant deduce that your formula is incorrect just by the path: "data".
I tested here and it does not work, it shows "hi{d", the inverse of the old code.
Sad
38260988133767770757751706102424708488397652359015616981186101000246135898
// above number mod 4294967296 (2 ^32) which is the max value for a unsigned interger you get 2520255578
rmewpq▒sad▒oamwpq▒lahokoy▒rpp▒clrowlaerpamatad
def encode(string):
result = 5381
for i in range(len(string)):
char = ord(string[i])
if char >= 65 and char <= 90:
char += 32
if char != 46 and char != 92:
result = (char + 33 * result)
return result
def decode(number):
result = ""
i = 0
while number != 5381:
char = number % 33;
while char < 97:
char += 33
if char > 129:
print("Data failure {0}".format(char))
exit()
number = (number - char) / 33
result += chr(char)
return result
encoded = encode("data\\map\\realworld_r\\01_yokohama\\105\\map_data\\105.emr")
print(encoded)
print(encoded % 4294967296) # mod for making a unsigned int (32bit)
print(decode(encoded))
Is the feature in question version dependent? If so what version are you using? Also if you have a current unpacked exe or an exe that launches with arguments for debugging purposes that would be helpful. Also an outline of your current goal or why you need this information, just because I may be able to come up with a different solution for the same problem. I had assumed you were trying to unpack the packing system. Nevermind about the outline, I see what you are attempting to do, I am testing things now.dTantra The game is Digimon Masters Online
Here is roughly 9,000 of them so far.dTantra The game is Digimon Masters Online
Here is roughly 9,000 of them so far.You must be registered to see linksI will have a lot more shortly
Can you tell us/me how you did it?
struct FileInfo
{
DWORD Hash;
const char * Filename;
};
FileInfo cFileInfo;
void ProcessFileHashInfo()
{
ofstream myfile;
myfile.open("filenames.txt", std::ios_base::app);
myfile << cFileInfo.Hash << "\t" << cFileInfo.Filename << "\n";
myfile.close();
}
__declspec(naked) void CC_ExtractFileHashInfo(void)
{
__asm
{
POP RetAddr
PUSH 0x00A04148
POP cFileInfo.Filename
PUSH cFileInfo.Filename
MOV cFileInfo.Hash, EDX
PUSHAD
PUSHFD
}
ProcessFileHashInfo();
__asm
{
POPFD
POPAD
PUSH RetAddr
ret
}
}
AddCodeCave(CC_ExtractFileHashInfo, 0x0045483D, 5);
Nice. As I think there is no way of getting the string from the hash, I think the only solution to make a file explorer for the "packed" files is to hard-code a list with the corresponding path. I will update my program to see how many hashes is missing.
__edit__
Only 1 hash missing for the 03 file, and 9791 for the 01 file. Nice. ;D
The annoying thing is that for every new added file, we have to edit the program...
Nice man. Would have any knoledge in the 3D files of this game, the *.nifs ? If you want to help us emulating this game, send me a PM with your skype, maybe we can work something out. ^_^
Nice man. Would have any knoledge in the 3D files of this game, the *.nifs ? If you want to help us emulating this game, send me a PM with your skype, maybe we can work something out. ^_^