You are on page 1of 20

:::TUTORIAL FOR TWELVE SKY MEMORY SEARCHING::: Here is a tutorial on how to: 1: Search out the address that

holds and updates your current Health using T-Search. 2: How to breakpoint that address to find out what Static addresses Write to it(update it). 3: How to use to OllyDbg to determine the OFFSET that points to your Current Health in Memory. Then how to get the Maximum Health OFFSET. 4: How to search for the Pointer Address from there that you will use with the OFFSET you found above to gain access to your current Health in memory as it is constantly being updated. 5: And last how to use the information you have obtained to make a small program that will automatically press your Pill key(1,2,3,or 4) when your health drops below the percent that you set. I will use a simple dll setup that will create a new thread. Using ReadProcessMemory in a loop within the new thread you will create your own pointers to the Maximum and Current Health values that can then be used to make a function for your AutoKeyPress at the time you want it to do so(50% HP & Below, 40% HP & Below ect...). NOTE: When Entering Addresses Into OllyDbg Remember To Add 0x In Front Of It Or It Will Not Recognize It. _____________________________________________________ --Step 1: Searching for the initial Health address.-_____________________________________________________ I will be using T-Search for this Tutorial as it is what I primarily use. First of all open up T-Search. Once T-Search is opened load up TwelveSky, Login to your account that you will be using(but make sure you have at least a few HP pills on your

character), and load up your character into the game. Now ALT+TAB out of the game and open up the game in T-Search. To do this, Click on the "Open Process" button in the upper left hand corner of the program. Now go back into the game and if your character is not in an area with mobs that can actually do some damage to it, then move your character to an area/zone where you can get some damage taken. Once there stop(make sure your health is full), then ALT+TAB back out to T-Search. Now you are going to start a new search. In T-Search you will need to click on the magnifying glass icon in the top left of the program just below the open process button. Now leave it how it is on the "Exact Value" and "4Byte" settings. In the "Value" field type in your Health and in T-Search hit "OK". Wait for it to complete then go ahead and hit "OK" again. Go back into the game now and fight a mob. Make sure lose a good amount of your health(I usually do about half) and then kill off the mob(so it dosen't keep hitting you while your scanning). Now ALT+TAB back out again. Now you will start another scan. This time you will be searching for "Changed Value". In T-Search go ahead and hit the second magnifying glass icon just to the right of the first one. In "Search" field where it says "Exact Value" hit the drop down list. Select the "Has Changed" option just below "Exact Value". Now hit "Ok" start the next the scan. Again wait for completion and hit "Ok" again. You should now get only one address in the list. If you have more than one address, just go back into the game and use HP Pills until you have full health again. Then do another search(using the second magnifying glass again) for your health again. By now you should have only one address in the list, if not just keep repeating the scans until you narrow it down. Now hit the yellow "+" sign to move the address entry over to the right field where you will be able to edit it. You should notice if you are still damaged it will be constantly going up. The address that I found was 1605C0.

This is a dynamic address so it will not be same on your computer nor will it be the same the next time you load the game(most of the time). To verify you found the correct address just look in-game at what your current health is and then ALT+TAB back out to T-Search and see where it is. Then Heal yourself fully and go back to T-Search again and you should see that it matches your health. Or you can just double click in the value field and change the value to whatever you like(ie: 1000000000). Then in-game it would look like for example: 1000000000/1025. Of course that is only visual and has absolutely no valuable effect, but at least you know that you have the right address. Next we need to set a breakpoint on that address to find the static address that writes to it(this address will not change when you reload the game). I will use OlyDbg to do this as it will break on just one Static address witch is all we need for the sake of our goal(Finding the Pointer address of your character and the OFFSETS that point to your Maximum and Current Health) so for the sake of this tutorial(assuming you are unfamiliar with all of this or don't know how to use breakpoints in OllyDbg, follow with the OllyDbg method first and then go back later if you want to try it in T-Search, and if you are familiar with memory scanning then skip past all of this and go to the ollydbg section). You can however BreakPoint your dynamic address with T-Search though, however it will return 5 different addresses each pertaining to a different function regarding your current health, such as Subtracting when taken damage or Adding when healed. You BreakPoint the address with T-Search by: 1: Clicking the "AutoHack" tab up on the top of the program. 2: Click on "Enable Debugger" from the dropdown list. 3: Click on "AutoHack Window" from the dropdown list. 4: In the "AutoHack Window" click on the edit tab up on the top of the window. 5: Click on "Set BreakPoint" from the dropdown list. 6: Now in the little window that pops up you need to make sure the "Type" field is set to "Write", and enter the address you just found into the address field. So go back to the original T-Search window, double on the address in the "Address" field until it is highlighted in blue(or just drag your mouse over it to highlight) right click and select copy. Now go back to the "AutoHack" window and paste into the address field. Now Click on "Set BreakPoint".

7: Ok now that your breakpoint is set on the address, You need to make your health change so that the game "writes" to the address in order for T-Search to read what addresses are writing to it. So go back into the game and take a couple of good hits from a mob. Kill the mob and then use Pills to fully heal yourself. 8: ALT+TAB Back out to T-Search and look in the "AutoHack" window. You will see 5 addresses now with there pertaining command. All of these addresses are static and will not change the next you load the game, they should also be the same on other machines. They all also have something to do with altering your current health status in-game. These are the addresses that I found: These should be the same for you as well, if not don't worry about, that is why we are going to find the Pointer. 407728: lea esi,[esp+0x70] // In this case the "ESP" register is holding the Pointer and 0x70 is the OFFSET. So ESP+0x70 is where your current HP is being held. 40A8AB: mov[ecx+0x168],edx // This is the address we will eventually use. ECX+0x168 in this case would be the pointer to your current HP, But we still need to find out what ECX is, that is where OllyDbg comes in. I have also found that if you set a breakpoint on this address and go into the game, it will break if you click something(Ground to move, Mob, ect). 44E002: sub[eax+ecx+168],edx // Subtracts the damage taken from your HP ammount and stores the value into the EDX Register. 44BBB6: add[eax+0x168],edx // Adds the Heal ammount to your Current HP ammount and stores the value into the EDX Register. 44BBF2: mov[edx+0x168],eax //Moves the New Current HP Value into the EAX Register. At this point we are done with T-Search. Make sure you remember the Dynamic Address you found(open notepad and paste/type it in for temp storage). Go ahead and close TSearch(if you followed the steps above and attached the debugger to breakpoint your address, since you attached a debugger to the game, when you close T-Search it will also close the game, in this case you will need to restart TSearch and do Step 1 over again, since the address you found was dynamic it will be different when you reload the game. Or you can just use the SECOND address in the list

from "AutoHack" (40A8AB: mov[ecx+0x168],edx) as this is the address that OllyDbg will Break on and the address we will use to find our pointer and offset). If you have a program to reset the debug port you can use that first and then close TSearch(Winject is a good example, Google it sometime if you would to try it), otherwise don't worry about it, just close out T-Search, reload the game, and either use the SECOND address from "AutoHack" or Re-Scan for the Dynamic HP Address. On to OllyDbg >>>:<<< _____________________________________________________ --Step 2: Setting a Breakpoint in OllyDebug.-_____________________________________________________ Once you have realoaded the game and have logged back into the game, go ahead and ALT+TAB back out of the game, go to the directory where you put your copy OllyDbg. Launch OllyDbg and attach it to the "TwelveSky.exe" Process in the Process list. If you do not have OllyDbg just google it, it is easy to find. The Current "Full" version is 1.10. You want to get the 1.10 version as 2.0 is still in alpha stages. OK I googled for the people that don't have it: http://www.ollydbg.de/ Look on the left side of the page under the "Files" Category. Click on the first file "ODbg110.zip". Download it. You will need winrar to open it(or winzip?). Make a new folder on your computer anywhere you want it, and extract the contents of the archive to that folder. Ok first I will give a breakdown of the Main 4 Windows we will be using: CPU View: The Biggest window in Upper Left Hand Corner, This is where all of the programs code is displayed and the main window you will work with. Register View: Upper Left Hand Corner, This is where the Registers are displayed and the current values/addresses

they hold. Hex Dump View: Bottom Left Hand Corner, Stack View: Bottom Right Hand Corner. Ok double click OLLYDBG.exe and launch it. Once its running you need to attach it to the game. Click on "File" "Attach Process", then scroll through the list of running processes until you find "TwelveSky.exe". Highlight "TwelveSky.exe" and hit "Attach". It will then begin loading all of the modules in the game. When it finishes attaching it then leave the game in a Paused state. To Unpause the game click the "Play" button on the top of the program just below the "Debug" tab. Note: if you leave the game paused for too long you will eventually get disconnected from the server. If this happens you just need to log back in, NONE of the addresses will change so you are safe and you don't have to re-do anything(even the dynamic address will be the same unless you reload the game entirely). Now first thing we need to do is get to the beggining of the "TwelveSky.exe" Module. Look at the top of the Olly window. There is a list of buttons with letters in white boxes. Click on the "E" button. Now double click on "TwelveSk". It should be the first one in the list. Note: In this view you can get the base address of the Module you are working with(in this case TwelveSky.exe). Here is what it should say: Base=00400000 Size=00AA0000 (11141120.) Entry=00401000 TwelveSk.<ModuleEntryPoint> Name=TwelveSk Path=C:\AeriaGames\12Sky\TwelveSky.exe so if you didn't know before and you should ever need the base address of a module in the game you are working with this is where you can find it. Ok now that you have double clicked on the "TwelveSk" Module it should bring you into the "CPU" view. You will have landed somewhere within the "NTDLL" Module. So go back to the Modules view("E" Button up top) and double click on "TwelveSk" one more time. Now you should be back in the CPU View at the entry of the "TwelveSky.exe" Module. You should be on this address: 00401000 > 8379 18 10 CMP DWORD PTR DS:[ECX+18],10 Hex Dump.

Now that we are in the "TwelveSky.exe" Module, go ahead and left click inside of the "Hex Dump" view. Now right click to bring up the menu of options. Find and select "Go To Expression"(or you can just press CTRL+G within the "Hex Dump" window, just make sure the "Hex Dump" is your active window). Now enter in the dynamic address that you found in T-Search. Hit "Ok". Your address is now the very first in the list on the "Hex Dump" view. Now you need to highlight the first 4 bytes(every 2 numbers is one byte, so for me it is: 71 02 00 00). Here is what it should look like: EXAMPLE: Address Hex dump ASCII ---------|------------------------------------------------|----001605C0 | 71 02 00 00 BB 00 00 00 BB 00 00 00 00 00 00 00| q............ 001605D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................ 001605E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................ Yours will be different depending on the address you found and your current HP ammount(the first 4 bytes are your Current Health), so if you are damaged as it continues healing you will see those numbers changing(You have left click in the "Hex Dump" view for it update the numbers though). Ok before we set the breakpoint we need to get damaged. So go into the game and get hit for at least half of your health(so it dosen't finish healing before the breakpoint is set), also make to sure to finish off the mob that you used to get damaged so you don't killed. Now ALT+TAB back out of the game, and with the first 4 bytes highlighted go ahead and right click again. In the Menu this time select the "BreakPoint" option. Select and Click on the "Memory, On Write" option. The game should pause immediately. Now take a look in the "CPU" window again. You should now have this address highlighted in the "CPU" View: 0040A8AB 8991 68010000 MOV DWORD PTR DS:[ECX+168],EDX

Take note of the information in the little area there just below the "CPU" window and just above the "Hex Dump" window.

This information will be very helpful for whatever you are looking for: EDX=00000204 //Value held in the EDX Register. DS:[001605C0]=00000200 //Notice your Dynamic Address printed between the brackets. NOTE: again yours will look different then mine. The dynamic address of course is different and the 2 values shown tend to change with your Current Health Ammount. Ok so now before we do anything else we need to remove our breakpoint and unpause the game. So left click back into the "Hex Dump" window and then right click again. Select the "BreakPoint" option again. Now this time click on the "Remove BreakPoint" option. Now hit the play button again to unpause the game so you don't get disconnected. _____________________________________________________ --Step 3: Using OllyDBG to get the OFFSET.-_____________________________________________________ Ok so now back to the address that we broke on in the "CPU" window: 0040A8AB 8991 68010000 MOV DWORD PTR DS:[ECX+168],EDX

This address should be the same on your computer as well, but if it is not the instruction is and that is the important thing. Right now looking at this instruction we have found our OFFSET to the Current HP Value: MOV DWORD PTR DS:[ECX+168],EDX // Move DWORD Pointer [ECX+168],EDX so it moves the value of the ECX Register + 0x168 into the EDX Register. ECX+168 holds our Current HP Value. So the OFFSET to the Current Health Value of your Character is: 0x168 Now we need to know the OFFSET for the Maximum Health Value. Subract 4 from 168 and that is the OFFSET to the Maxium

Health. 0x164 0x168

So our OFFSETS are: // Maximum Health OFFSET // Current Health OFFSET

_____________________________________________________ --Step 4: Using OllyDBG to get the Player Pointer.-_____________________________________________________ So, now that we have OFFSETS that point to both our Max and Cur Health Values we need to know the pointer address of our character. So we take another look at the instruction: MOV DWORD PTR DS:[ECX+168],EDX //Since ECX+168 is the Pointer to our Current HP Value then the pointer Address that we need to find is stored in ECX. So first thing we need to do is scroll up in the function from our address containing the HP and look for something that sets the EAX register. We are looking for something like this as an example: MOV ECX,DWORD PTR DS:[657D48] real function //Just an example, not a

or sometimes it will be like this: MOV EAX,DWORD PTR DS:[ECX] //In this case you would need continue scrolling up until you find what sets EAX. Until you find the address. IE: MOV EAX,DWORD PTR DS:[657D48] Ok so back to our function. In this case it is really simple to find the pointer as it is only 2 lines above our original address. Here is the address that holds our POINTER+OFFSET and a few lines above: 0040A876 0040A87C 0040A880 0040A884 8B0D E0A7D000 8B4424 30 8B7424 34 893D CC32A900 MOV MOV MOV MOV ECX,DWORD EAX,DWORD ESI,DWORD DWORD PTR PTR DS:[D0A7E0] PTR SS:[ESP+30] PTR SS:[ESP+34] DS:[A932CC],EDI

0040A88A A3 5033A900 MOV DWORD PTR DS:[A93350],EAX 0040A88F 8935 5433A900 MOV DWORD PTR DS:[A93354],ESI 0040A895 8959 68 MOV DWORD PTR DS:[ECX+68],EBX 0040A898 8B15 E0A7D000 MOV EDX,DWORD PTR DS:[D0A7E0] 0040A89E 897A 6C MOV DWORD PTR DS:[EDX+6C],EDI 0040A8A1 8B0D E0A7D000 MOV ECX,DWORD PTR DS: [D0A7E0] //Ah, ECX, Move ECX, DWORD POINTER [D0A7E0] ECX = D0A7E0 0040A8A7 8B5424 28 MOV EDX,DWORD PTR SS:[ESP+28] 0040A8AB 8991 68010000 MOV DWORD PTR DS: [ECX+168],EDX //Our Address that Holds our POINTER+OFFSET to CUR HP. 0040A8B1 8B0D E0A7D000 MOV ECX,DWORD PTR DS:[D0A7E0] 0040A8B7 8B5424 2C MOV EDX,DWORD PTR SS:[ESP+2C] 0040A8BB 8991 70010000 MOV DWORD PTR DS:[ECX+170],EDX 0040A8C1 8B0D E0A7D000 MOV ECX,DWORD PTR DS:[D0A7E0] 0040A8C7 8981 D4000000 MOV DWORD PTR DS:[ECX+D4],EAX 0040A8CD 8B0D E0A7D000 MOV ECX,DWORD PTR DS:[D0A7E0] 0040A8D3 8B81 D8000000 MOV EAX,DWORD PTR DS:[ECX+D8] So now to access our Current Health we just need do: 0xD0A7E0+0x168; One way to use this in a program: DWORD dwBytesRead; DWORD dwPlayerBase; address into: 0xD0A7E0 DWORD dwCurrentHealth; health value into DWORD dwMaximumHealth; health into //Pointer to store original BYTES //Pointer to store our pointer //Pointer to store our current //and pointer to store our max

ReadProcessMemory(HANDLE, (void*)0xD0A7E0, &dwPlayerBase, sizeof(dwPlayerBase), &dwBytesRead);//Reads the memory at the //---------//address 0xD0A7E0. //BreakDown: //---------/*HANDLE = pointer to the process to read from(ie: TwelveSky.exe) will set that up in the next step.

0xD0A7E0 = Address to read from. &dwPlayerBase = Our Pointer to store our Pointer Address into from above, The function reads the memory at the address supplied and stores it into our Pointer dwPlayerBase. sizeof(dwPlayerBase) = reads the size(ammount of bytes) // BYTES READ BELOW dwBytesRead = stores the bytes at the address(ie: the instruction) 0040A8D3 8B81 D8000000 MOV EAX,DWORD PTR DS[ECX+D8] ------------*/ ReadProcessMemory(HANDLE, (void*)(dwPlayerBase+0x168), &dwCurrentHealth, sizeof(dwCurrentHealth), &dwBytesRead); //---------BreakDown: //---------//Same as above except now we use our POINTER+OFFSET to store our CurrentHealth Value into our own Pointer: dwCurrentHealth ReadProcessMemory(HANDLE, (void*)dwPlayerBase+0x164), &dwMaximumHealth, sizeor(dwMaximumHealth), &dwBytesRead); //---------BreakDown: //---------//Same as above except now we use our POINTER+OFFSET to store our CurrentHealth Value into our own Pointer: dwMaximumHealth Now that we have our Maximum Health and Current Health stored into our pointers we can use them to create a function to automaically send a keypress at the correct time. Source Code below for a simple dll project. _____________________________________________________ --Step 5: Putting all of this information to use ---_____________________________________________________

Now I will give an example project source code for a simple dll that will attach to the 12Sky Process, and Create a new thread, in the thread there will be a loop and inside the loop goes the code from above and the function to send the keypress to heal. The loop will force the program to keep updating the information so that the pointers created above will always hold the 2 Health values. Without the loop it will just read the information once and currenthealth will never update, it would just stay as it was when the dll was first attached to the process. So here is the code and explaination of the functions within: / ************************************************************ ************************************************************ ************************************************************ ************************************************************ ***** ************************************ TWELVE SKY EXAMPLE DLL PROJECT ******************************************************* *********************************** +______________________________+ *******************000000000************************** ***************************************** AUTO HEALING BOT ************************************************************ **** ************************************************************ ************************************************************ ************************************************************ ************************************************************ *****/ // /* Multi Line Comment */ //Commenting is used for any text within the source that you don't want the compiler to read #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <iostream> Single Line Comment

#include <time.h> #include <stdio.h> #include <sys/types.h> #include <sys/timeb.h> #include <string.h> using namespace std; #define FILELOCATION "C:\\12SkyHelper\\12Sky.log" the output directory for the log file void __cdecl add_log(const char * fmt, ...); log function //Define //For the

HANDLE TwelveSky = GetCurrentProcess(); //HANDLE = Points to the Process/Module to read from HWND SkyWnd = FindWindow(0, "TwelveSky"); //Used to read if TwelveSky is the active window //DWORD PID = GetPIDbyTitle("TwelveSky"); //Function from the winject source to find the current //DWORD PID2 = GetPIDbyClass("TwelveSky"); //process's PID. Its just here for future use. Remove it if you //like or you can google for "Winject Source" and add it to your //project . DWORD dwBytesread; //Stores the original bytes from the address read DWORD dwCurHealth; //All of our pointers that will hold our HP/MP Information and Our Base Pointer Address DWORD dwMaxHealth; DWORD dwPlayerBase; DWORD dwCurMP; DWORD dwMaxMP; bool UseMed = true;//Boolean value to decipher weather or not to use the MedKey function or to just use pills for MP BYTE MedKey = VK_F5;//Value to tell the program which key to use float HPPercent = 0.5;//Float value to determine what percentage of health we must either reach or drop below to auto heal float MPPercent = 0.5;//Same as above on for MP DWORD Slot1;//Pointers for the Pill Slots to read weather they have pills or they are empty DWORD Slot2; DWORD Slot3;

DWORD Slot4; #define VK_1 0x31 //Define key 1-4 because it won't compile if you try to use VK_1-9 #define VK_2 0x32 #define VK_3 0x33 #define VK_4 0x34 int SendKeyStroke(BYTE TheKeyToSend) function { keybd_event(TheKeyToSend, MapVirtualKey(TheKeyToSend, 0), 0, 0); keybd_event(TheKeyToSend, MapVirtualKey(TheKeyToSend, 0), KEYEVENTF_KEYUP, 0); return 1; } DWORD ReadThread(LPVOID lpArgs) { add_log("Thread Started."); while(1) { //5579AC Pointer for GM Commands :) //Our AutoKeyPress //KeyDown Event

//KeyUp Event

//Our Thread //Start the Loop

//:::::: OUR READPROCESSMEMORY FUNCTIONS TO STORE THE VALUES OF HP/MP INTO OUR POINTERS ::::::\\ //HANDLE TwelveSky = GetCurrentProcess(); ReadProcessMemory(TwelveSky, (void*)(0xD0A7E0), &dwPlayerBase, sizeof(dwPlayerBase), &dwBytesread); ReadProcessMemory(TwelveSky, (void*) (dwPlayerBase+0x164), &dwMaxHealth, sizeof(dwMaxHealth), &dwBytesread); ReadProcessMemory(TwelveSky, (void*) (dwPlayerBase+0x168), &dwCurHealth, sizeof(dwCurHealth), &dwBytesread); /*Our OFFSETS for MP can be found the same way as we found the HP. Once you get the dynamic address of MP by scanning T-Search, BreakPoint it in OllyDbg, at the address that it breaks on you will find ECX+170 in the instruction. This is of course your Current MP Pointer. Subtract 4 from 170 and you get 16C(hex)*/

ReadProcessMemory(TwelveSky, (void*) (dwPlayerBase+0x170), &dwCurMP, sizeof(dwCurMP), &dwBytesread); ReadProcessMemory(TwelveSky, (void*) (dwPlayerBase+0x16C), &dwMaxMP, sizeof(dwMaxMP), &dwBytesread); //Read from the Pointer addresses of all 4 Pill Slots and store the value(ammount of pills) to our own pointer ReadProcessMemory(TwelveSky, (void*)(0xA93864), &Slot1, sizeof(Slot1), &dwBytesread); ReadProcessMemory(TwelveSky, (void*)(0xA9386C), &Slot2, sizeof(Slot2), &dwBytesread); ReadProcessMemory(TwelveSky, (void*)(0xA93874), &Slot3, sizeof(Slot3), &dwBytesread); ReadProcessMemory(TwelveSky, (void*)(0xA9387C), &Slot4, sizeof(Slot4), &dwBytesread); DWORD HealHealth = dwMaxHealth * HPPercent; // use our MaxHealth Pointer and Multiply it by the float value we set above DWORD RestoreMP = dwMaxMP * MPPercent; // same but with the MaxMP Pointer if(SkyWnd == GetForegroundWindow()) //Makesure TwelveSky is the Active window so It dosen't send Keypresses when you are { //minimized for(dwCurHealth; dwCurHealth <= HealHealth; dwCurHealth++)//setup a loop for Current Health, if the CurrentHealth { //is less than or equal the HealHealth(MaxHealth*HPPercent //witch is set to 0.5 by default. 0.4 40% 0.3 30% 0.6 60% if(Slot1 > 0) //Make sure Slot1 has pills(Slot1 Greater than 0) { SendKeyStroke(VK_1); //Send the KeyPress add_log("Your HP was just Restored via Slot1"); //Add to the log alerting a keypress } else if((Slot1 == 0) && (Slot2 > 0)) //If slot1 is empty use and Slot2 has pills use slot2

{ SendKeyStroke(VK_2); add_log("Your HP was just Restored via Slot2"); Slot2");} no pills } for(dwCurMP; dwCurMP <= RestoreMP; dwCurMP++)//same as the HP but using the MP Pointers { if(!UseMed) //If Not UseMed(if the bool UseMed is set to false continue) { if(Slot3 > 0) //check slot3 for pills { SendKeyStroke(VK_3); add_log("Your MP was just Restored via Slot3"); } else if((Slot3 == 0) && (Slot4 > 0)) //slot3 out of pills, check slot4 and use it if there are pills { SendKeyStroke(VK_4); add_log("Your MP was just Restored via Slot4"); } else {add_log("Add MP Pills to Slot3 or Slot4");} //Alert out of pills } if(UseMed) // if the bool value UseMed is set to True it will use your meditation skill instead of MPPills { // use this when you are poor SendKeyStroke(MedKey); //use the sendkeystroke like normal but use the Variable MedKey so that it can be //can be custom set via a config(config to be added at a later time) add_log("Your MP is being Restored via Meditation"); } } } Sleep(1000);//Pause for 1000 miliseconds(1second) or else the thread lags the program horribly } else {add_log("Add HP Pills to Slot1 or //if both slot1 and 2 are empty alert to the log

} return 0; } BOOL WINAPI DllMain (HINSTANCE hModule, DWORD dwAttached, LPVOID lpvReserved) //dll main, attach to process { if (dwAttached == DLL_PROCESS_ATTACH) //attach to process { DeleteFile(FILELOCATION); //Deletes old log to start a new one CreateThread( NULL, NULL,(LPTHREAD_START_ROUTINE) ReadThread , NULL, NULL, NULL); // create our thread add_log("--------------------------"); //just some logging add_log("--------------------------"); add_log("----New Log Started-------"); add_log("Attached to 12Sky Client"); add_log("--------------------------"); add_log("--------------------------"); add_log("Thread Created."); //add_log("PID = %d", PID); //used this with winject source code to find the current PID of TwelveSky.exe //add_log("PID = %d", PID2); } if (dwAttached == DLL_PROCESS_DETACH) //Detach DLL { add_log("DLL Detached from 12Sky Client"); //log detach } return 1; } void __cdecl add_log(const char * fmt, ...) // and last the logging function { #ifndef _NO_ADD va_list va_alist; char logbuf[256]; FILE * fp; struct tm * current_tm; time_t current_time; time (&current_time); current_tm = localtime (&current_time);

sprintf (logbuf, "[%02d:%02d:%02d] ", current_tm>tm_hour, current_tm->tm_min, current_tm->tm_sec); va_start (va_alist, fmt); _vsnprintf (logbuf+strlen(logbuf), sizeof(logbuf) strlen(logbuf), fmt, va_alist); va_end (va_alist); if ( (fp = fopen ( FILELOCATION , "a")) != NULL ) { fprintf ( fp, "%s\n", logbuf ); fclose (fp); } #endif _NO_ADD } / ************************************************************ ************************************************************ ************************************************************ ************************************************************ ************************************************************ ************************************************************ ************************************************************ ************************************************************ ************************************************************ ************************************************************ ************************************************************ ************************************************************ ****************/ Hopefully it helps out and hopefully I didn't make too many mistakes. I think I typed it out pretty clearly but please if there is anything that is confusing of spelling errors or the like point it out to me and I will fix it. Hopefully this will spark a little bit of interest in TwelveSky and we will see at least a small ammount of releases for the game. Or at the very least it may help someone to find pointers for whatever game they may want them for. /*NOTES: To find the Pill Slot addresses just place a certain of Pills into the slot and search that value in TSearch(leave it at "Exact Value" and "4 Bytes". Then go in-

game and remove about 20 Pills. Then search the value of however many Pills are left in the Slot. Then add some back and search the new value. Rinse and Repeate until you are down to only one address. Do the same thing for all 4 Slots. These address's are static so once you find all 4 address's in T-Search you are done and ready to add them to your program. MP can be the same as HP(but its a bit easier, not having to get damaged and all). Just get your MP full, Search the Value("Exact Value" "4 Byte"). Then use a skill, use your buff skill. Go and search for "Changed Value". It should now isoloate one Dynamic address. If not just rinse and repeat the process until you have the one address. Then go to Olly and search for the OFFSET of Current MP the same way you did with HP(you don't need to search for the Pointer because it is the same as HP 0xD0AE70). As of Twelve Sky Client Version 1.10, you should find 0x170 to be the OFFSET for Current MP. Subtract that offset by 4 to obtain the Maximum MP offset(the values are in hex, so use calc in scientific mode with hex selected). You will come up with 16C(Client Version 1.10). Now you can find the Pointer and the OFFSETS needed to update the source code for any future Client Release of Twelve Sky. This way you should always have a working AUTO HEAL/MP.RESTORE program for any version.*/ *********************************************** *********************************************** ***** COMPILING THE SOURCE CODE INTO A DLL **** *********************************************** *********************************************** You will need to install a C++ compiler. If you don't have one there are some free ones out there. Off the top of my head I know of, DevC++ by BloodShed(google it), and you can an Express Edition of Microsoft Visual Studio from their website(google it). Or you can go to warez if you want a full version of Visual Studio(I currently use Visual Studio 2003 .net). Assuming your using Visual studio you want to start a new project. Go to Win32. Select Win32Project(not console

app). Enter the name, and directory(C:\SomeFolderName, thats easiest for me). Next Page click application settings and select dll and empty project. Then click finish. Your Project is created. Now copy the source code above to an empty Notepad document, and then saveas into the C:\SomeFolderName directory as WHATEVERYOUWANTTONAMEIT.cpp Then in Visual Studio and look on the right hand side, Under Solution Explorer. There will be a list of items. At the very top it will say "Solution 'YOURPROJECTNAME'" and just below that it just says "YOURPROJECTNAME". Click on that then right click on it. Choose "Add" "Add Existing Item", now navigate to your C:\SomeFolderName Directory and double click on the WHATEVERYOUWANTTONAMEIT.cpp. Now look around the Mid-Top of the program you see the work "Debug" with a dropdown list. Bring down that list and select "Release". Now go to "Build", and Click on "Build YOURPROJECTNAME". Now it should compile without errors and you can find your YOURPROJECTNAME.dll in the C:\SomeFolderName\Release directory. Now just get an injector, start 12Sky and login to the game, Inject the dll into TwelveSky.exe.

You might also like