This repository was archived by the owner on Apr 7, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b4d028d
Showing
111 changed files
with
9,133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
function ExtractMsgTable() { | ||
var offset = exe.find(" 3F 41 56 56 4E 49 49 6E 70 75 74 4D 6F 64 65 40", PTYPE_HEX, false); | ||
if (offset == -1) { | ||
return "Failed in Part 1"; | ||
} | ||
if (exe.getClientDate() <= 20130605) { | ||
offset += 0x23; | ||
} | ||
else { | ||
offset += 0x1D3; | ||
} | ||
|
||
var done = false; | ||
var id = 0; | ||
var fp = new TextFile(); | ||
fp.open(APP_PATH + "/Output/msgstringtable_" + exe.getClientDate() + ".txt", "w"); | ||
while (!done) { | ||
if (exe.fetchDWord(offset) == id) { | ||
var start_offset = exe.Rva2Raw(exe.fetchDWord(offset+4)); | ||
var end_offset = exe.find(" 00", PTYPE_HEX, false, " ", start_offset); | ||
var msgstr = exe.fetch(start_offset, end_offset - start_offset); | ||
msgstr = msgstr.replace(/\r\n/g, "\n"); | ||
fp.writeline(msgstr + "#"); | ||
offset += 0x08; | ||
id++; | ||
} | ||
else { | ||
done = true; | ||
} | ||
} | ||
fp.close(); | ||
return "Msgstringtable has been Extracted to NEMO's path"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
function ExtractTxtNames() { | ||
|
||
var rOffset = exe.getROffset(DATA); | ||
var rEnd = rOffset + exe.getRSize(DATA); | ||
|
||
var offsets = exe.findAll(" 2E 74 78 74 00", PTYPE_HEX, false, " ", rOffset, rEnd); | ||
if (offsets.length == 0) { | ||
return "No .txt files found"; | ||
} | ||
|
||
var fp = new TextFile(); | ||
fp.open(APP_PATH + "/Output/loaded_txt_files_" + exe.getClientDate() + ".txt", "w"); | ||
fp.writeline("Extracted with NEMO"); | ||
fp.writeline("-------------------"); | ||
for(var i = 0; i < offsets.length; i++) { | ||
var offset = offsets[i]; | ||
var end = offset + 3; | ||
var dt; | ||
do { | ||
offset--; | ||
dt = exe.fetchByte(offset); | ||
} while (dt != 0 && dt != 0x40); | ||
|
||
var str = exe.fetch(offset+1,end - offset); | ||
if (str !== ".txt") {//Skip ".txt" | ||
fp.writeline(str); | ||
} | ||
} | ||
fp.close(); | ||
return "Txt File list has been extracted to Output folder"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
function findStart(off, type) {//type=1 PUSH ESI, type=2 PUSH EBX | ||
var code = " 83 EC 0C 56 8B F1"; | ||
var range = 0x20; | ||
|
||
if (type === 2) { | ||
code = " 83 EC 0C 53"; | ||
range = 0x50; | ||
} | ||
|
||
var startoff = exe.find(" 55 8B EC" + code, PTYPE_HEX, false, " ", off - range, off); | ||
if (startoff === -1) { | ||
startoff = exe.find(code, PTYPE_HEX, false, " ", off - range, off); | ||
} | ||
return startoff; | ||
} | ||
|
||
|
||
function GenMapEffectPlugin() { | ||
var fp = new BinFile(); | ||
if (!fp.open(APP_PATH + "/Input/rdll2.asi")) { | ||
return "Base File - rdll2.asi is missing from Input folder..Exiting"; | ||
} | ||
|
||
var errorStr = "Script needs update"; | ||
var xmasRVA = exe.findString("xmas_fild01.rsw", RVA); | ||
if (xmasRVA === -1) { | ||
return errorStr; | ||
} | ||
|
||
var CGIEntry = exe.findCode(xmasRVA.packToHex(4) + " 8A", PTYPE_HEX, false); | ||
if (CGIEntry === -1) { | ||
return errorStr; | ||
} | ||
CGIEntry--; | ||
|
||
var CGIExit = exe.find("E8 AB AB AB AB 8A", PTYPE_HEX, true, "\xAB", CGIEntry + 5); | ||
if (CGIExit === -1) { | ||
return errorStr; | ||
} | ||
var LCl = CGIExit + 5 + exe.fetchDWord(CGIExit+1); | ||
CGIExit += 5; | ||
|
||
var yunoRVA = exe.findString("yuno.rsw", RVA); | ||
if (yunoRVA === -1) { | ||
return errorStr; | ||
} | ||
var CGOEntry = exe.find(" B8" + yunoRVA.packToHex(4), PTYPE_HEX, false, " ", 0, CGIEntry-1); | ||
if (CGOEntry === -1) { | ||
CGOEntry = exe.find(" B8" + yunoRVA.packToHex(4), PTYPE_HEX, false, " ", CGIExit+8); | ||
} | ||
if (CGOEntry === -1) { | ||
return errorStr; | ||
} | ||
|
||
var CGOExit = exe.find("C7 AB AB AB AB AB FF 8B AB AB AB AB 00 8B", PTYPE_HEX, true, "\xAB", CGOEntry); | ||
if (CGOExit === -1) { | ||
return errorStr; | ||
} | ||
CGOExit += 7; | ||
|
||
var LNt = exe.findCode(" C6 01 01 C3", PTYPE_HEX, false); | ||
if (LNt === -1) { | ||
return errorStr; | ||
} | ||
|
||
var offsets = exe.findCodes("81 F9 2C 01 00 00 7E AB B9", PTYPE_HEX, true, "\xAB"); | ||
if (offsets.length !== 3) { | ||
return errorStr; | ||
} | ||
|
||
var LSk = 0; | ||
var LSn = 0; | ||
var LMp = 0; | ||
|
||
for (var i = 0; i < 3; i++) { | ||
var offset = findStart(offsets[i], 1); | ||
if (exe.find(" 68 A2 00 00 00", PTYPE_HEX, false, " ", offsets[i], offsets[i]+0x60) !== -1) { | ||
LSn = offset; | ||
} | ||
else if (exe.find(" 68 A3 00 00 00", PTYPE_HEX, false, " ", offsets[i], offsets[i]+0x60) !== -1) { | ||
LSk = offset; | ||
} | ||
else if (exe.find(" 68 4D 01 00 00", PTYPE_HEX, false, " ", offsets[i], offsets[i]+0x60) !== -1) { | ||
LMp = offset; | ||
} | ||
} | ||
if (LSn === -1 || LSk === -1 || LMp === -1) { | ||
return errorStr; | ||
} | ||
|
||
offsets = exe.findCodes("68 2D 01 00 00", PTYPE_HEX, false); | ||
var LPk = findStart(offsets[1], 2); | ||
if (LPk === -1) { | ||
return errorStr; | ||
} | ||
|
||
var offset = exe.find("B9 AB AB AB 00 E8", PTYPE_HEX, true, "\xAB", CGIEntry-0x10, CGIEntry); | ||
if (offset === -1) { | ||
return errorStr; | ||
} | ||
var GW = exe.fetchHex(offset+1,4); | ||
var GU = 0; | ||
|
||
var df = 0; | ||
|
||
offset = exe.find("B9" + GW + " 39 1D", PTYPE_HEX, false); | ||
|
||
if (offset === -1) { | ||
offset = exe.find("A1 AB AB AB 00 B9" + GW, PTYPE_HEX, true, "\xAB"); | ||
df = 1; | ||
} | ||
else { | ||
df = 7; | ||
} | ||
|
||
if (offset === -1) { | ||
return errorStr; | ||
} | ||
|
||
GU = exe.fetchHex(offset+df, 4); | ||
|
||
offset = exe.findCode("8B 0D AB AB AB 00 68 01 02 00 00 50", PTYPE_HEX, true, "\xAB"); | ||
if (offset === -1) { | ||
return errorStr; | ||
} | ||
|
||
var GC = exe.fetchHex(offset+2,4); | ||
|
||
var PEOff = exe.find(" 50 45 00 00", PTYPE_HEX, false); | ||
if (PEOff === -1) { | ||
return errorStr; | ||
} | ||
|
||
var TS = exe.fetchHex(PEOff+0x08,4); | ||
|
||
var dll = fp.readHex(0,0x2000); | ||
fp.close(); | ||
|
||
dll = dll.replace(/ 29 35 83 4F/i, TS); | ||
dll = dll.replace(/ A0 1B 97 00/i, GW); | ||
dll = dll.replace(/ D8 3D 8F 00/i, GC); | ||
dll = dll.replace(/ EC 0E 9A 00/i, GU); | ||
dll = dll.replace(/ 80 68 6C 00/i, exe.Raw2Rva(LCl).packToHex(4)); | ||
dll = dll.replace(/ 60 66 6C 00/i, exe.Raw2Rva(LSn).packToHex(4)); | ||
dll = dll.replace(/ C0 68 6C 00/i, exe.Raw2Rva(LMp).packToHex(4)); | ||
dll = dll.replace(/ 40 68 6C 00/i, exe.Raw2Rva(LSk).packToHex(4)); | ||
dll = dll.replace(/ 30 6B 6C 00/i, exe.Raw2Rva(LPk).packToHex(4)); | ||
dll = dll.replace(/ E0 6B 6C 00/i, exe.Raw2Rva(LNt).packToHex(4)); | ||
|
||
dll = dll.replace(/ 61 AB 72 00/i, exe.Raw2Rva(CGIEntry).packToHex(4)); | ||
dll = dll.replace(/ 48 B4 72 00/i, exe.Raw2Rva(CGIExit ).packToHex(4)); | ||
dll = dll.replace(/ ED 37 73 00/i, exe.Raw2Rva(CGOEntry).packToHex(4)); | ||
dll = dll.replace(/ 08 49 73 00/i, exe.Raw2Rva(CGOExit ).packToHex(4)); | ||
|
||
fp.open(APP_PATH + "/Output/rdll2_" + exe.getClientDate() + ".asi", "w"); | ||
fp.writeHex(0,dll); | ||
fp.close(); | ||
|
||
/* - Use incase you need the source file | ||
fp2 = new TextFile(); | ||
fp2.open(APP_PATH + "/Output/client_" + exe.getClientDate() + ".h", "w"); | ||
fp2.writeline("#include <WTypes.h>"); | ||
fp2.writeline("\n//Client Date : " + exe.getClientDate()); | ||
fp2.writeline("#define CLIENT_TIMESTAMP " + le2be(TS)); | ||
fp2.writeline("\n//Client offsets"); | ||
fp2.writeline("void* G_WEATHER = (void*)" + le2be(GW) + ";"); | ||
fp2.writeline("void** G_CRENDERER = (void**)" + le2be(GC) + ";"); | ||
fp2.writeline("void* G_USEEFFECT = (void*)" + le2be(GU) + ";"); | ||
fp2.writeline("\nDWORD CWeather_EffectId2LaunchFuncAddr[] = {\n\tNULL, //CEFFECT_NONE"); | ||
fp2.writeline("\t" + le2be(exe.Raw2Rva(LCl).packToHex(4)) + ", // CEFFECT_SKY -> void CWeather::LaunchCloud(CWeather this<ecx>, char param)"); | ||
fp2.writeline("\t" + le2be(exe.Raw2Rva(LSn).packToHex(4)) + ", // CEFFECT_SNOW -> void CWeather::LaunchSnow(CWeather this<ecx>)"); | ||
fp2.writeline("\t" + le2be(exe.Raw2Rva(LMp).packToHex(4)) + ", // CEFFECT_MAPLE -> void CWeather::LaunchMaple(CWeather this<ecx>)"); | ||
fp2.writeline("\t" + le2be(exe.Raw2Rva(LSk).packToHex(4)) + ", // CEFFECT_SAKURA -> void CWeather::LaunchSakura(CWeather this<ecx>)"); | ||
fp2.writeline("\t" + le2be(exe.Raw2Rva(LPk).packToHex(4)) + ", // CEFFECT_POKJUK -> void CWeather::LaunchPokJuk(CWeather this<ecx>)"); | ||
fp2.writeline("\t" + le2be(exe.Raw2Rva(LNt).packToHex(4)) + ", // CEFFECT_NIGHT -> void CWeather::LaunchNight(CWeather this<ecx>)"); | ||
fp2.writeline("};\n"); | ||
fp2.writeline("void* CGameMode_Initialize_EntryPtr = (void*)" + le2be(exe.Raw2Rva(CGIEntry).packToHex(4)) + ";"); | ||
fp2.writeline("void* CGameMode_Initialize_RetPtr = (void*)" + le2be(exe.Raw2Rva(CGIExit ).packToHex(4)) + ";"); | ||
fp2.writeline("void* CGameMode_OnInit_EntryPtr = (void*)" + le2be(exe.Raw2Rva(CGOEntry).packToHex(4)) + ";"); | ||
fp2.writeline("void* CGameMode_OnInit_RetPtr = (void*)" + le2be(exe.Raw2Rva(CGOExit ).packToHex(4)) + ";"); | ||
fp2.close(); | ||
*/ | ||
|
||
return "MapEffect plugin for the loaded client has been generated in Output folder"; | ||
} | ||
|
||
function le2be(le) { | ||
var be = ""; | ||
for (var i = le.length-3; i >= 0; i-=3) { | ||
be += le.substring(i,i+3); | ||
} | ||
return "0x" + be.replace(/ /g,""); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
function le2be(le) { | ||
var be = ""; | ||
for (var i = le.length-3; i >= 0; i-=3) { | ||
be += le.substring(i,i+3); | ||
} | ||
return "0x" + be.replace(/ /g,""); | ||
} | ||
|
||
function GetPacketKeys() { | ||
var key = new Array(); | ||
if (exe.getClientDate() == 20131223) {//Shared Key and code change | ||
var code = | ||
' B8 AB AB AB AB' // MOV EAX, Third Key | ||
+ ' 89 41 08' // MOV DWORD PTR DS:[ECX+8], EAX -- Second key | ||
+ ' 89 41 0C' // MOV DWORD PTR DS:[ECX+0C], EAX -- Third key | ||
+ ' C7 41 04' // MOV DWORD PTR DS:[ECX+4], First Key | ||
; | ||
var offset = exe.findCode(code, PTYPE_HEX, true, "\xAB"); | ||
if (offset == -1) { | ||
return "Unsupported Client - looks like it is corrupted"; | ||
} | ||
|
||
key[0] = le2be(exe.fetchHex(offset+14,4));//First Key | ||
key[1] = le2be(exe.fetchHex(offset+01,4));//Second Key | ||
key[2] = key[1];//Third Key | ||
} | ||
else { | ||
var code = | ||
' 8B 0D AB AB AB 00' //MOV ecx, DS:[ADDR1] dont care what | ||
+ ' 68 AB AB AB AB' //PUSH key1 <- modify these | ||
+ ' 68 AB AB AB AB' //PUSH key2 <- | ||
+ ' 68 AB AB AB AB' //PUSH key3 <- | ||
+ ' E8' //CALL encryptor | ||
; | ||
|
||
var offsets = exe.findCodes(code, PTYPE_HEX, true, "\xAB"); | ||
if (offsets.length !== 2) { | ||
return "Unable to find the keys - Addon needs to be updated to support the client"; | ||
} | ||
|
||
key[0] = le2be(exe.fetchHex(offsets[0]+17,4));//First Key | ||
key[1] = le2be(exe.fetchHex(offsets[0]+12,4));//Second Key | ||
key[2] = le2be(exe.fetchHex(offsets[0]+07,4));//Third Key | ||
} | ||
var fp = new TextFile(); | ||
fp.open(APP_PATH + "/Output/PacketKeys_" + exe.getClientDate() + ".txt", "w"); | ||
|
||
fp.writeline("Packet Keys : (" + key[0] + " , " + key[1] + " , " + key[2] + " )"); | ||
fp.close(); | ||
return "Packet Keys have been written to Output folder"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
//Register all your Addons in this file. All addons need to be registered to appear in NEMO | ||
// | ||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
//FORMAT for registering Addon : registerAddon(functionName, description, Tooltip text); | ||
// | ||
// functionName is the function called when an addon is clicked. All your logic goes inside it. | ||
// You can define your function in any .qs file in the Addons folder. | ||
// Remember the functionName needs to be in quotes (single or double) here but no quotes should be used while defining it. | ||
// | ||
// description is what shows up in the Addon menu of NEMO. | ||
// tooltip - text which shows detail about what a particualar tool/addon does - need to check if its actually visible. | ||
// | ||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
registerAddon("ExtractMsgTable", "Extract msgstringtable", "Extracts embedded msgstringtable from the loaded client"); | ||
|
||
registerAddon("ExtractTxtNames", "Extract txt file names", "Extracts embedded txt file names in the loaded client"); | ||
|
||
registerAddon("GetPacketKeys", "Get Packet Keys", "Retrieves the packet keys used in the loaded client for Obfuscation"); | ||
|
||
//registerAddon("GenMapEffectPlugin", "Generate Mapeffect plugin by Curiosity", "Generates Curiosity's mapeffect plugin for loaded client"); | ||
//Disabled since it needs to be fixed. | ||
|
Oops, something went wrong.