Category Archives: C/C++

Unpacking FFXi Related Files

One of the many aspects of reversing Final Fantasy XI be it statically on disk or live in memory requires that parts of the game files are unpacked. Square Enix has taken the time to create an internal packer of the games sensitive data for the PE files (.exe and .dll). In many of the game files, there is a packed section called POL1. This section contains the files actual .text section data, but is packed.

For example, this is the games FFXiMain.dll as of Jan 01, 2015:
FFXiMain Sections

In this image you’ll see something strange. The files .text section has a raw size of 0. This is because the actual data does not exist in the file until its unpacked. Instead, the files .text data is actually within the POL1 section. If we load FFXiMain.dll inside of OllyDbg, or any other debugger / disassembler, we will see this at the files current entry point:
FFXiMain Unpacking Routine

Like much of SE’s other packing / encoding methods, the encryption of the section is not very secure or unique.
Some basic shifting and such and the unpacked data is obtained fairly easily.

However, handling this unpacking externally from a static context is a bit more difficult because it involves having to rebuild the PE file on disk after it is unpacked. The .text section must be resized to its proper size containing the new raw data which in turn unaligns all the other sections. So each section must be rebuilt and realigned with the file. Afterward, we must also set the files new size and its new entry point.

Unpacking the file is fairly trivial, we can just steal the decryption method from the games file and use it locally. If we adjust the ASM as needed, we can reuse it like this:

;*******************************************************************************
; XiUnpack.asm (c) 2014 atom0s [atom0s@live.com]
;
; Unpacks a given POL1 section from a file.
; This function is taken from the FFXiMain.dll file.
;*******************************************************************************

.586
.model flat, C
option casemap :none

.code

    ;*******************************************************************************
    ; @brief Unpacks the given POL1 section.
    ;
    ; @param packed         The packed POL1 section to unpack.
    ; @param unpacked       The unpacked buffer to write the data to.
    ;*******************************************************************************
    XiUnpack PROC
        PUSHAD
        MOV EBP, ESP
        MOV ESI, DWORD PTR SS:[EBP + 024h] ; packed section
        MOV EDI, DWORD PTR SS:[EBP + 028h] ; storage
jmp_6:
        MOV ECX, 8
        MOV BL, BYTE PTR DS:[ESI]
        INC ESI
jmp_5:
        SHL BL, 1
        JNB jmp_1
        MOV AL, BYTE PTR DS:[ESI]
        MOV BYTE PTR DS:[EDI], AL
        INC ESI
        INC EDI
        JMP jmp_2
jmp_1:
        XOR EAX, EAX
        MOV AL, BYTE PTR DS:[ESI]
        INC ESI
        MOV EDX, EAX
        MOV AL, BYTE PTR DS:[ESI]
        MOV AH, DL
        AND EAX, 0FFFh
        JE jmp_3
        INC ESI
        NEG EAX
        SHR EDX, 4
        ADD EDX, 3
jmp_4:
        MOV BH, BYTE PTR DS:[EDI + EAX]
        MOV BYTE PTR DS:[EDI], BH
        INC EDI
        DEC EDX
        JNZ jmp_4
jmp_2:
        LOOP jmp_5
        JMP jmp_6
jmp_3:
        POPAD
        RETN
    XiUnpack ENDP
END

This would allow us to call XiUnpack to unpack the POL1 section like this:

XiUnpack((DWORD)ptr_to_packed_data, (DWORD)ptr_to_output_buffer);

So the last bit would be now to load the file locally, dump the PE file information including:

  • DOS Header
  • DOS Stub (If it exists.)
  • Nt Headers
  • Section Entries
  • Section Data

Here is a step by step run down of what we would need to do. I will post the source code to this on Github as well for those interested.

  1. Load the file locally into memory.
  2. Validate the file is a PE file.
  3. Validate the file has a packed POL1 section.
  4. Obtain the POL1 section for its data and raw size.
  5. Obtain the .text section for its virtual size. (This is the size of POL1 unpacked.)
  6. Invoke XiUnpack, as seen above, to unpack the data.
  7. Begin Rebuilding The Unpacked File
    1. Write the original DOS header to the new file.
    2. Write the DOS stub, if it exists, to the new file.
    3. Write the original NT headers to the new file.
    4. Process each section of the file.
      1. If .text section, set the size of raw data to its virtual size.
      2. Set the sections raw data pointer to the previous sections end. (Realigning the sections.)
      3. Realign the sections pointer to raw data and size of raw data to the files section alignment. (Required for Windows to consider the file valid!)
      4. Write the section entry to the file.
      5. Set the file pointer to the sections raw data offset.
      6. Write the sections raw data to the file.
      7. Reset the file pointer to the section table for the next section to be written.
  8. Reset the file pointer to the NT headers offset.
  9. Adjust the files SizeOfImage inside of the NT headers with the new last section information.
  10. Rewrite the NT headers to the file with the new image size.
  11. Close the new file.

At this point our new file should be all set. The result will look something like this:
Unpacked

As you can see here, our .text section is now properly sized (and aligned) to the file. Following the raw data pointer will take us to the unpacked data from POL1 as well. Each following section has had their raw address set to their new locations following the .text’s section data. Setting the raw data pointer is as simple as (rawSize + rawAddress) of the section previous. .text starts at 0x00001000. The next section will start at (.text->RawSize + .text->RawAddress). And so on for each following section.

Something to keep in mind, the POL1 section is not required after being unpacked. We have reset the entry point of the file to its new location. This allows us to completely remove the section if we wanted. Doing so will require us to fix the .rsrc and .reloc sections to properly align in the file with the POL1 section removed. For this example and source base, I just left the section in place. It does not hurt having it there, it just takes up some extra space.

Some side notes on how certain information is handled..

Aligning The Sections
According to MSDN, ‘SizeOfRawData’ and ‘PointerToRawData’ must be section aligned. It is required to be a multiple of the files ‘FileAlignment’ value found within the NT headers optional header. This is simple to do. Because it needs to be a multiple we want to make sure we are rounding up. In order to do, we would do the following:

(((in + align - 1) / align) * align)

So as an example, our .text section in FFXiMain.dll would look like this:

PointerToRawData = (((0x400 + 0x200 - 1) / 0x200) * 0x200); // would equal: 0x400
SizeOfRawData = (((0x2F4C2E + 0x200 - 1) / 0x200) * 0x200); // would equal: 0x2F4E00

Obtaining The Entry Point
With the example code base that is on Github, we will see the following for the entry point:

        auto baseAddressOffset = *(DWORD*)(((DWORD)packed + polSection.Misc.VirtualSize) - 0x51);
        auto baseAddressOriginal = ntHeaders.OptionalHeader.AddressOfEntryPoint;
        ntHeaders.OptionalHeader.AddressOfEntryPoint = (baseAddressOffset + baseAddressOriginal) + 0x9B;

Here we are reading the original code from the packed file. The first read is the jump offset to the last jump going to the actual original entry point. Next, we obtain the original entry point then we calculate the original from the given offset. The + 0x9B is the offset to the last JMP to the entry point. So we are calculating the difference from the original entry point to the real entry point based on the jump.

Github link: https://github.com/atom0s/xiunpack

Simple Memory Scanner Example

Wrote this for someone that was asking for help on Cheat Engine’s forums. This is a very very basic and light-weight memory scanner that will scan for 4 byte values.

/** 
 * Simple Memory Scanner Example 
 * (c) 2014 atom0s [atom0s@live.com] 
 */ 

#include <Windows.h> 
#include <string> 
#include <TlHelp32.h> 

/** 
 * @brief The target process to scan within. 
 */ 
#define TARGET_NAME "winmine.exe" 

/** 
 * @brief Obtains the process id of the given target. 
 * 
 * @return The process id if found, 0 otherwise. 
 */ 
unsigned int getTargetProcessId() 
{ 
    PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) }; 

    // Obtain a snapshot of the current process list.. 
    auto handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
    if (handle == INVALID_HANDLE_VALUE) 
        return 0; 

    // Obtain the first process.. 
    if (!::Process32First(handle, &pe32)) 
    { 
        ::CloseHandle(handle); 
        return 0; 
    } 

    // Loop each process looking for the target.. 
    do 
    { 
        if (!_stricmp(pe32.szExeFile, TARGET_NAME)) 
        { 
            ::CloseHandle(handle); 
            return pe32.th32ProcessID; 
        } 
    } while (::Process32Next(handle, &pe32)); 

    // Cleanup.. 
    ::CloseHandle(handle); 
    return 0; 
} 

/** 
 * @brief Entry point of this application. 
 * 
 * @param argc  The count of arguments passed to this application. 
 * @param argv  The array of arguments passed to this application. 
 * 
 * @return Non-important return. 
 */ 
int __cdecl main(int argc, char* argv[]) 
{ 
    // Obtain the target process id.. 
    auto processId = getTargetProcessId(); 
    if (processId == 0) 
        return 0; 

    // Open a handle to the target.. 
    auto handle = ::OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId); 
    if (handle == INVALID_HANDLE_VALUE) 
        return 0; 

    // Obtain the current system information.. 
    SYSTEM_INFO sysInfo = { 0 }; 
    ::GetSystemInfo(&sysInfo); 

    auto addr_min = (long)sysInfo.lpMinimumApplicationAddress; 
    auto addr_max = (long)sysInfo.lpMaximumApplicationAddress; 

    auto found = 0; 

    // Loop the pages of memory of the application.. 
    while (addr_min < addr_max) 
    { 
        MEMORY_BASIC_INFORMATION mbi = { 0 }; 
        if (!::VirtualQueryEx(handle, (LPCVOID)addr_min, &mbi, sizeof(mbi))) 
        { 
            printf_s("Failed to query memory.\n"); 
            break; 
        } 

        // Determine if we have access to the page.. 
        if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_GUARD) == 0) && ((mbi.Protect & PAGE_NOACCESS) == 0)) 
        { 
            // 
            // Below are flags about the current region of memory. If you want to specifically scan for only 
            // certain things like if the area is writable, executable, etc. you can use these flags to prevent 
            // reading non-desired protection types. 
            // 

            auto isCopyOnWrite = ((mbi.Protect & PAGE_WRITECOPY) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0); 
            auto isExecutable = ((mbi.Protect & PAGE_EXECUTE) != 0 || (mbi.Protect & PAGE_EXECUTE_READ) != 0 || (mbi.Protect & PAGE_EXECUTE_READWRITE) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0); 
            auto isWritable = ((mbi.Protect & PAGE_READWRITE) != 0 || (mbi.Protect & PAGE_WRITECOPY) != 0 || (mbi.Protect & PAGE_EXECUTE_READWRITE) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0); 

            // Dump the region into a memory block.. 
            auto dump = new unsigned char[mbi.RegionSize + 1]; 
            memset(dump, 0x00, mbi.RegionSize + 1); 
            if (!::ReadProcessMemory(handle, mbi.BaseAddress, dump, mbi.RegionSize, NULL)) 
            { 
                printf_s("Failed to read memory of location: %08X\n", mbi.BaseAddress); 
                break; 
            } 

            // Scan for 4 byte value of 1337.. 
            for (auto x = 0; x < mbi.RegionSize - 4; x += 4) 
            { 
                if (*(DWORD*)(dump + x) == 1337) 
                    found++; 
            } 

            // Cleanup the memory dump.. 
            delete[] dump; 
        } 

        // Step the current address by this regions size.. 
        addr_min += mbi.RegionSize; 
    } 

    printf_s("Found %d results!\n", found); 

    // Cleanup.. 
    ::CloseHandle(handle); 
    return ERROR_SUCCESS; 
}

Grim Dawn File Archive / Database Extractors

I’ve recently bought Grim Dawn after wanting an offline ARPG to play while my internet is utter shit or offline. I stumbled across Grim Dawn by accident doing some Google searches looking for something that has a similar Diablo feel to it. GD happens to be by the makers of Titan Quest, which I did enjoy somewhat when I was younger, however I never really got too in depth with playing it. But from the look of the game having that Diablo 2 look and feel, I wanted to give it a try.

Fast forward to now, I’ve been personally interested in the game data files to see how things are stored, what is where, and so on as a local lookup for information about the game, such as where monsters spawn, what they drop, and such. Which lead to the creation of the two following tools.

grimarc – Grim Dawn Archive File Extractor (.arc)
This is a simple tool to extract the .arc archive files for Grim Dawn.
https://github.com/atom0s/grimarc

grimarz – Grim Dawn Database File Extractor (.arz)
This is a simple tool to extract the .arz database files for Grim Dawn.
https://github.com/atom0s/grimarz

At this time, these tools are simply for static analysis locally, they do not offer any ability to edit, read, modify or repackage the files they have since extracted. My interest is simply in seeing the content of the files, not to modify them.

Desktop Cleanup – Old Code

Here is a method of [quickly] caching prime numbers:

	// Prepare prime number cache.
	std::bitset&lt; 10000 &gt; bsPrimeNumbers = 0;
	bsPrimeNumbers.flip();
	bsPrimeNumbers.set( 0, false );
	bsPrimeNumbers.set( 1, false );

	// Create prime number cache.
	for( size_t x = 0; x * x &lt; bsPrimeNumbers.size(); x++ )
	{
		if( bsPrimeNumbers.test( x ) )
		{
			for( size_t y = x * x; y &lt; bsPrimeNumbers.size(); y += x )
				bsPrimeNumbers.set( y, false );
		}
	}

Credits to:
– Starblue: http://stackoverflow.com/questions/1042902/most-elegant-way-to-generate-prime-numbers/1043247#1043247

His implementation was in Java that I converted to C++ for a web challenge.

Desktop Cleanup – Old Code

Here’s a small bit of code to read the players inventory in Final Fantasy XI.

#include <Windows.h>
#include <iostream>
#include <TlHelp32.h>

typedef struct _ITEM_ENTRY {

	unsigned char _unk1[ 40 ];
	unsigned long ItemBasePtr;
	unsigned long ItemId;
	unsigned long ItemCount;
	unsigned char _unk3[ 28 ];

} ITEM_ENTRY, *LPITEM_ENTRY;

typedef struct _MENU_HEADER {
	unsigned char _unk1[ 70 ];
	unsigned char Description[ 17 ];
} MENU_HEADER;

typedef struct _MENU_STRUCT {

	//unsigned char _unk1[ 4 ];
	unsigned long	_unk1;
	unsigned long	MenuHeader;
	unsigned long	UnknownPtr;
	unsigned long	MenuDetails;

	unsigned char	_unk3[ 60 ];

	unsigned long	Index;

} MENU_STRUCT;

DWORD GetProcess( void )
{
	PROCESSENTRY32 pe32 = { sizeof( pe32 ) };
	HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
	if( hSnapshot == INVALID_HANDLE_VALUE )
		return 0;

	if( ! Process32First( hSnapshot, &pe32 ) )
	{
		CloseHandle( hSnapshot );
		return 0;
	}

	do {
		if( _stricmp( pe32.szExeFile, "pol.exe" ) == 0 )
		{
			CloseHandle( hSnapshot );
			return pe32.th32ProcessID;
		}
	} while( Process32Next( hSnapshot, &pe32 ) );

	CloseHandle( hSnapshot );
	return 0;
}

DWORD GetModule( DWORD dwProcessId )
{
	MODULEENTRY32 me32 = { sizeof( me32 ) };
	HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId );
	if( hSnapshot == INVALID_HANDLE_VALUE )
		return 0;

	if( ! Module32First( hSnapshot, &me32 ) )
	{
		CloseHandle( hSnapshot );
		return 0;
	}

	do {
		if( _stricmp( me32.szModule, "ffximain.dll" ) == 0 )
		{
			CloseHandle( hSnapshot );
			return reinterpret_cast< DWORD >( me32.modBaseAddr );
		}
	} while( Module32Next( hSnapshot, &me32 ) );

	CloseHandle( hSnapshot );
	return 0;
}

int __cdecl main( int argc, char* argv[] )
{
	DWORD dwProcess = GetProcess();
	DWORD dwModule = GetModule( dwProcess );

	DWORD dwMenuPtr		= (dwModule + 0xF8882);
	DWORD dwPointer		= 0;
	HANDLE hHandle		= OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwProcess );
	
	MENU_STRUCT menuStruct = { 0 };
	MENU_HEADER menuHeader = { 0 };
	ReadProcessMemory( hHandle, (LPVOID)dwMenuPtr, &dwPointer, 4, NULL );
	ReadProcessMemory( hHandle, (LPVOID)dwPointer, &dwPointer, 4, NULL );
	ReadProcessMemory( hHandle, (LPVOID)dwPointer, &menuStruct, sizeof( menuStruct ), NULL );
	ReadProcessMemory( hHandle, (LPVOID)menuStruct.MenuHeader, &menuHeader, sizeof( MENU_HEADER ), NULL );

	menuStruct.Index = menuStruct.Index;

	CloseHandle( hHandle );
	return 0;
}

This code is fairly old so the pointers/offsets are bound to be off. The structures probably changed since this was written so you will more then likely have to alter things for it to work as expected.

Disclaimer:
I do not own Final Fantasy XI; I am not the owner of their property or their name.
Final Fantasy XI is copyright to the following:

© 2001 – 2011 SQUARE ENIX CO., LTD. All Rights Reserved. FINAL FANTASY, SQUARE ENIX, and the SQUARE ENIX logo are registered trademarks of Square Enix Holdings Co., Ltd. Vana’diel , Tetra Master, PLAYONLINE, the PLAYONLINE logo, Rise of the Zilart, Chains of Promathia, Treasures of Aht Urhgan, and Wings of the Goddess are registered trademarks of Square Enix Co., Ltd. The Online icon is a trademark of Sony Computer Entertainment America Inc. “PlayStation” and the “PS” Family logo are registered trademarks of Sony Computer Entertainment Inc. Microsoft, Xbox, Xbox 360, Xbox LIVE, and the Xbox logos are trademarks of the Microsoft group of companies and are used under license from Microsoft. The rating icon is a registered trademark of the Entertainment Software Association. All other trademarks are the property of their respective owners. Online play requires internet connection.

Desktop Cleanup – Old Code

This was an example of how to download the favorite icon from a website I wrote for someone on Cheat Engine’s forums.


#pragma comment( lib, "WS2_32.lib" )
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>

// Site to [attempt to] download icon from.
std::string g_vSite = "www.google.com";
std::string g_vIcon = "favicon.ico";

int main( int argc, TCHAR* argv[] )
{
	WSADATA wsaData = { 0 };
	if( WSAStartup( MAKEWORD( 2, 0 ), & wsaData ) != 0 )
	{
		std::cout << "WSAStartup failed with error: " << WSAGetLastError() << std::endl;
		return 0;
	}

	SOCKET sock = { 0 };
	if( ( sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ) ) < 0 )
	{
		std::cout << "socket failed with error: " << WSAGetLastError() << std::endl;
		WSACleanup();
		return 0;
	}

	struct hostent* rhostent = { 0 };
	rhostent = gethostbyname( g_vSite.c_str() );

	struct sockaddr_in saddr = { 0 };
	saddr.sin_family		= AF_INET;
	saddr.sin_addr.s_addr	= *(u_long*)rhostent->h_addr_list[0];
	saddr.sin_port			= htons( 80 );

	if( connect( sock, (struct sockaddr *)&saddr, sizeof( sockaddr_in ) ) < 0 )
	{
		std::cout << "connect failed with error: " << WSAGetLastError() << std::endl;
		closesocket( sock );
		WSACleanup();
		return 0;
	}

	// Build HTTP GET request to obtain icon file.
	std::string strHttpRequest = "GET /favicon.ico HTTP/1.0rn";
	strHttpRequest += "Host: " + g_vSite + "rn";
	strHttpRequest += "rn";

	if( send( sock, strHttpRequest.c_str(), strHttpRequest.length(), 0 ) != strHttpRequest.length() )
	{
		std::cout << "send failed with error: " << WSAGetLastError() << std::endl;
		closesocket( sock );
		WSACleanup();
		return 0;
	}

	// Retrieve buffer from request.
	std::string strHttpResponse;
	char szBuffer[ 512 ] = { 0 };
	int nReadSize = 512;

	while( nReadSize > 0 )
	{
		nReadSize = recv( sock, (char*)&szBuffer, 512, NULL );
		if( nReadSize == 0 ) break;
		strHttpResponse += std::string( szBuffer ).substr( 0, nReadSize );
	}

	// Cleanup and return.
	closesocket( sock );
	WSACleanup();

	return 0;
}

References used:
http://www.zedwood.com/article/113/cpp-winsock-basic-http-connection
http://msdn.microsoft.com/en-us/library/ms738524%28v=vs.85%29.aspx

Runes of Magic

Since I don’t have much to post about I do want to keep updating this blog a bit more frequently. So here is some old information I worked on from an MMO called Runes of Magic. This is some old info so it could be outdated, so if it doesn’t line up fully its probably due to updates.

Player structure: (Fairly certain all mobs used this, but I don’t fully remember.)

typedef struct _MOBENTRY {

    unsigned long   _unk1;          // 0x00 - Pointer / Id?
    unsigned long   WarpStruct;     // 0x04 - Warp structure x/z/y etc.
    unsigned char   _unk2[12];      // 0x08 - Unknown Data
    unsigned long   ObjectId;       // 0x14 - Object identification?
    unsigned long   ObjectType;     // 0x18 - Object Type Flag
    unsigned long   _unk3;          // 0x1C - Seems to always be 1.
    unsigned long   _unk4;          // 0x20 - Seems to be a pointer to something.
    unsigned long   _unk5;          // 0x24 - Seems to always be 0.
    float           WorldX;         // 0x28 - Position X in world. (Read-only)
    float           WorldZ;         // 0x2C - Position Z in world. (Read-only)
    float           WorldY;         // 0x30 - Position Y in world. (Read-only)
    float           Heading1;       // 0x34 - Looking direction. (Camera left/right.)
    float           Camera1;        // 0x38 - Camera position up/down.
    float           Heading2;       // 0x3C - Looking direction. (Unsure, it turns your char as well.)
    float           Speed;          // 0x40 - Speed
    unsigned char   _unk6[16];      // 0x44 - Unknown Data
    float           ModelTilt1;     // 0x54 - Model tilt axis. (Backward.) (Read-only)
    float           _unk7;          // 0x58 - Forced 0.
    unsigned long   _unk8;          // 0x5C - Unknown
    float           ModelTilt2;     // 0x60 - Model tilt axis. (Backward.) (Editable)
    float           _unk9;          // 0x64 - Changes _unk7 - model positioning possibly?
    float           _unk10;         // 0x68 - Unknown
    float           _unk11;         // 0x6C - Unknown
    float           ModelScale1;    // 0x70 - Scaling of model. (1 = normal, 2 = huge, 0 = tiny.)
    float           ModelScale2;    // 0x74 - Scaling of model. (Possible multipler?)
    float           Transparency;   // 0x78 - Model transparency. (1 = full, 0.5 = half, 0 = invis.)

    unsigned char   _unk12[532];    // 0x7C - Unknown Data
    
    char*           Name;           // 0x290
    char*           Title;          // 0x294
    char*           Guild;          // 0x298
};

Friend of mine and I worked hard to reverse the damage calculations for defense as well and came up with:

(This could also be invalid now, it was only off by around %0.098 when we tested and figured it out.)

modifier = 
	if( self-pattack &lt; target-pdef )
		penalty = (( self-pattack / target-pdef ) / target-pdef) * 100 
	else
		bonus = ((( self-pattack / target-pdef ) / self-pattack ) + 1 ) * 100

( 100 + modifier )% of ( self-damage / attack-speed ) = white_damage_hit

Just cleaning up my desktop and figured I’d post these in case anyone wants them.

psopchax – Plugin SDK Released

Released the plugin SDK for psopchax this morning. Here’s what an example plugin would look like:

#define STRICT
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN

#include &lt;windows.h&gt;

// psopchax Plugin SDK Includes
#include &lt;psopchax-psdk/IConsole.hpp&gt;
#include &lt;psopchax-psdk/IHookManager.hpp&gt;
#include &lt;psopchax-psdk/IPluginManager.hpp&gt;
#include &lt;psopchax-psdk/Plugin.h&gt;

// ----------------------------------------------------------------------------------------------
//
// Plugin GUID
//
// ----------------------------------------------------------------------------------------------

extern &quot;C&quot; const GUID __declspec( selectany ) pluginGuid = {
	0x5b6558ab, 0xdd50, 0x4cea, 0xae, 0x3e, 0x4f, 0xfe, 0x9a, 0x5d, 0x3f, 0x66
};

// ----------------------------------------------------------------------------------------------
//
// Plugin Information
//
// ----------------------------------------------------------------------------------------------

PLUGININFO pluginInfo = {
	sizeof( PLUGININFO ),
	PLUGIN_HEADER_VERSION,
	PLUGIN_FLAG_NONE,
	pluginGuid,
	0x00000001,
	&quot;Walk Through Walls&quot;,
	&quot;Disables player collision detection.&quot;,
	&quot;atom0s&quot;
};

// ----------------------------------------------------------------------------------------------
//
// Patch Entries
//
// ----------------------------------------------------------------------------------------------

BYTE btPatch1_Enable[]	= { 0xEB, 0x1C };
BYTE btPatch2_Enable[]	= { 0xEB, 0x1A, 0x90, 0x90, 0x90, 0x90 };
BYTE btPatch3_Enable[]	= { 0xEB, 0x1E };
BYTE btPatch4_Enable[]	= { 0xEB, 0x1C, 0x90, 0x90, 0x90, 0x90 };

BYTE btPatch1_Disable[] = { 0x75, 0x1C };
BYTE btPatch2_Disable[] = { 0x89, 0x86, 0x20, 0x03, 0x00, 0x00 };
BYTE btPatch3_Disable[] = { 0x75, 0x1E };
BYTE btPatch4_Disable[] = { 0x89, 0x86, 0x20, 0x03, 0x00, 0x00 };

// ----------------------------------------------------------------------------------------------
//
// Patch Addresses
//
// ----------------------------------------------------------------------------------------------

DWORD dwAddress1 = 0x00577980;
DWORD dwAddress2 = 0x005779AB;
DWORD dwAddress3 = 0x00577B1B;
DWORD dwAddress4 = 0x00577B48;

// ----------------------------------------------------------------------------------------------
//
// Custom Memory Editor
//
// ----------------------------------------------------------------------------------------------

HRESULT _memcpy_vec( LPVOID lpDest, const LPVOID lpSource, int nSize )
{
	std::vector&lt; MEMORY_BASIC_INFORMATION &gt; m_vMemInformation;
	BYTE* btCurrentPage = reinterpret_cast&lt; BYTE* &gt;( lpDest );

	while( btCurrentPage &lt; ( reinterpret_cast&lt; BYTE* &gt;( lpDest ) + nSize ) )
	{
		MEMORY_BASIC_INFORMATION mbi = { 0 };
		if( VirtualQuery( reinterpret_cast&lt; LPVOID &gt;( btCurrentPage ), &amp;mbi, sizeof( mbi ) ) )
			m_vMemInformation.push_back( mbi );
		btCurrentPage = ( reinterpret_cast&lt; BYTE* &gt;( mbi.BaseAddress ) + mbi.RegionSize );
	}

	DWORD dwOldProtect = 0;
	for( int x = 0; x &lt; static_cast&lt; int &gt;( m_vMemInformation.size() ); x++ )
		VirtualProtect( m_vMemInformation[x].BaseAddress, m_vMemInformation[x].RegionSize, PAGE_READWRITE, &amp;dwOldProtect );

	memcpy( lpDest, lpSource, nSize );

	for( int x = 0; x &lt; static_cast&lt; int &gt;( m_vMemInformation.size() ); x++ )
		VirtualProtect( m_vMemInformation[x].BaseAddress, m_vMemInformation[x].RegionSize, m_vMemInformation[x].Protect, &amp;dwOldProtect );

	return S_OK;
}

// ----------------------------------------------------------------------------------------------
//
// CWalkThroughWalls Class
//
// ----------------------------------------------------------------------------------------------

class CWalkThroughWalls : public IPlugin
{
	IConsole*		m_vConsole;
	IHookManager*	m_vHookManager;
	IPluginManager* m_vPluginManager;

public:
	CWalkThroughWalls( void ) : m_vConsole( 0 ), m_vHookManager( 0 ), m_vPluginManager( 0 )
	{
	}
	~CWalkThroughWalls( void )
	{
	}

public:
	HRESULT __stdcall OnCreate( IHookManager* pHookManager, IConsole* pConsole, IPluginManager* pPluginManager )
	{
		this-&gt;m_vConsole		= pConsole;
		this-&gt;m_vHookManager	= pHookManager;
		this-&gt;m_vPluginManager	= pPluginManager;

		// Apply Memory Patches
		_memcpy_vec( reinterpret_cast&lt; LPVOID &gt;( dwAddress1 ), &amp;btPatch1_Enable, sizeof( btPatch1_Enable ) );
		_memcpy_vec( reinterpret_cast&lt; LPVOID &gt;( dwAddress2 ), &amp;btPatch2_Enable, sizeof( btPatch2_Enable ) );
		_memcpy_vec( reinterpret_cast&lt; LPVOID &gt;( dwAddress3 ), &amp;btPatch3_Enable, sizeof( btPatch3_Enable ) );
		_memcpy_vec( reinterpret_cast&lt; LPVOID &gt;( dwAddress4 ), &amp;btPatch4_Enable, sizeof( btPatch4_Enable ) );

		return S_OK;
	}
	HRESULT __stdcall OnDestroy( void )
	{
		// Remove Memory Patches
		_memcpy_vec( reinterpret_cast&lt; LPVOID &gt;( dwAddress1 ), &amp;btPatch1_Disable, sizeof( btPatch1_Disable ) );
		_memcpy_vec( reinterpret_cast&lt; LPVOID &gt;( dwAddress2 ), &amp;btPatch2_Disable, sizeof( btPatch2_Disable ) );
		_memcpy_vec( reinterpret_cast&lt; LPVOID &gt;( dwAddress3 ), &amp;btPatch3_Disable, sizeof( btPatch3_Disable ) );
		_memcpy_vec( reinterpret_cast&lt; LPVOID &gt;( dwAddress4 ), &amp;btPatch4_Disable, sizeof( btPatch4_Disable ) );

		// Cleanup Class Objects
		this-&gt;m_vConsole		= NULL;
		this-&gt;m_vHookManager	= NULL;
		this-&gt;m_vPluginManager	= NULL;

		return S_OK;
	}
};

// ----------------------------------------------------------------------------------------------
//
// Required Plugin Exports
//
// ----------------------------------------------------------------------------------------------

__declspec( dllexport ) boost::shared_ptr&lt; IPlugin &gt; __stdcall pluginCreateInstance( void )
{
	return boost::shared_ptr&lt; IPlugin &gt;( new CWalkThroughWalls );
}
__declspec( dllexport ) HRESULT __stdcall pluginGetInfoStruct( PLUGININFO&amp; p )
{
	p = pluginInfo;
	return S_OK;
}

This would allow players to walk through walls in game, removing the collision detection between the world and their characters. Simple enough. As said the plugin system is based on Dr. Dobb’s plugin tutorials, a great read if you haven’t read it yourself and are interested in plugin systems.

PS: WordPress sucks for posting code -.- missing a nice chunk of things since this is not formatted for html.

FontFactory v2! – Plus more randomness..

FontFactory v2 is go! Sakuri and I got time to work on it a few days ago and really pushed it fast. Basically it is FontFactory just redone using FreeType v2 to load fonts in a better fashion then using the CreateFont API.

At the moment the new FontFactory is a bit ‘raw’ and static towards what it can do, meaning it doesn’t have all the spiffy features the original had, but, it does have the key elements.

Things left to fix/add:
– Bold font.
– Italic font.
– Font quality.

Things working:
– Font.
– Font coloring.
– Backgrounds.

Things added:
– Tabbing, both vertical and horizontal tabs. ( v and t )
– Fixed background flag.
– Absolute fixed background flag.

Currently, all fonts are loaded using FreeType v2’s custom hinting code for creating very good quality clear type fonts. Which is actually pretty nice looking. However, I still want to reimplement some other features as listed above to give it the customization abilities like before. We’ll see how things go with that.

We have added the ‘Fixed Background‘ flag to the new version. What this flag does is allows you to create a font object with a background with a static size set to what you wish, height and width. However, the object glyphs can cause the background to shift locations still with this flag. (Meaning certain characters can move the object some still.)

We have also added the ‘Absolute Fixed Background‘ flag to accommodate for the small shifts that are caused by the ‘fixed background’ flag. This flag forces the background to stay where it is told, regardless of the fonts text.

So why the change to FreeType v2? Well, the main reason is due to the limitations of the old version. The old version does not allow for the use of JP characters, meaning anyone using it would be forced to use standard English. This caused many issues with one of the main targets for the project as the player base for FFXi is not just NA.

FreeType v2 allows us to render ALL characters inside a font file now. With little to no known limitations at the moment. This means JP, German, Latin, Chinese, etc. should all work as long as the chosen font can handle those characters.

Sakuri and I are still new to FreeType and how it is used, so improvements are expected to happen at random as we learn more about it and what it is able to do. 🙂 But as for the ‘alpha’ test version, so far so good.

Here is a new screenshot of the working FontFactory v2:

As for other goodies, I have started working on various fixes, changes and updates to the console and other parts of the core classes. The base of the plugin system is written, however major changes are going to be done to it as it is still too crash-unsafe at the moment.

The CVar class has bee fully rewritten and is working good so far. I have implemented callbacks with them as well so they can notify a function on a change to their value. The CVar class is exposed to Lua as well so you can have lua functions as callbacks.

The plugin system is still iffy.. it needs a lot of work and needs to be reintegrated with the whole core to be better suited for using internal objects. (It can access the console, the lua engine, etc. but it is not thread safe and is very prone to crashing.)

The basic screenshot class is updated to handle BMP and PNG now. JPG will come later if at all.

The Lua engine has gotten some updates, nothing major just some minor tweaks to adjust to other changes.

I plan to rewrite everything again once I get a better base worked out but for now, things are going ok.