Hello,
You want to stop people from extracting your client with Python?
It's actually pretty simple but this is a tutorial for advanced users ...
First we need a new pack module:
Now we need to replace
CharacterManagerModule:
Add:
and add also:
and the system.py
Search:
Replace the whole function:
If your python code does not load any files with pack_open or pack.Get you can remove the pack.Get function.
:rolleyes:
You want to stop people from extracting your client with Python?
It's actually pretty simple but this is a tutorial for advanced users ...
First we need a new pack module:
Code:
bool packExist(char* strFileName)
{
// ÆÄÀ̽㿡¼* Àоîµå¸®´Â ÆÐÅ· ÆÄÀÏÀº python ÆÄÀϰú txt ÆÄÀÏ¿¡ ÇÑÁ¤ÇÑ´Ù
const char* pcExt = strrchr(strFileName, '.');
if (pcExt) // È®ÀåÀÚ°¡ ÀÖ°í
{
if ((stricmp(pcExt, ".py") == 0) ||
//(stricmp(pcExt, ".pyc") == 0) ||
(stricmp(pcExt, ".txt") == 0))
{
return CEterPackManager::Instance().isExist(strFileName);
}
}
return false;
}
PyObject * packImportAsModule(PyObject* poSelf, PyObject * poArgs)
{
char* strFileName;
if (!PyTuple_GetString(poArgs, 0, &strFileName))
return Py_BuildException();
if (packExist(strFileName))
{
CMappedFile file;
const void * pData = NULL;
if (CEterPackManager::Instance().Get(file, strFileName, &pData))
{
PyObject* co = Py_CompileString((const char*)pData, strFileName, Py_file_input);
std::string moduleName = CFileNameHelper::NoExtension(std::string(strFileName));
PyObject* newCo = PyImport_ExecCodeModule(const_cast<char*>(moduleName.c_str()), co);
return Py_BuildValue("S", newCo);
}
}
return Py_BuildValue("b", 0);
}
PyObject * packExist(PyObject * poSelf, PyObject * poArgs)
{
char * strFileName;
if (!PyTuple_GetString(poArgs, 0, &strFileName))
return Py_BuildException();
return Py_BuildValue("i", packExist(strFileName));
}
PyObject * packGet(PyObject * poSelf, PyObject * poArgs)
{
char * strFileName;
if (!PyTuple_GetString(poArgs, 0, &strFileName))
return Py_BuildException();
if (packExist(strFileName))
{
CMappedFile file;
const void * pData = NULL;
if (CEterPackManager::Instance().Get(file, strFileName, &pData) && strlen((const char *)pData) == file.Size())
return Py_BuildValue("s#",pData, file.Size());
}
return Py_BuildException();
}
void initpack()
{
static PyMethodDef s_methods[] =
{
{ "Exist", packExist, METH_VARARGS },
{ "Get", packGet, METH_VARARGS }, // remove this after you implemented everything to load npclist and other files with the binary
{ "ImportAsModule", packImportAsModule, METH_VARARGS },
{ NULL, NULL },
};
Py_InitModule("VFSImporter", s_methods);
}
Code:
void CPythonCharacterManager::LoadNPCList()
{
const VOID* pvData;
CMappedFile kFile;
if (!CEterPackManager::Instance().Get(kFile, "npclist.txt", &pvData))
return;
CMemoryTextFileLoader textFileLoader;
textFileLoader.Bind(kFile.Size(), pvData);
CTokenVector TokenVector;
for (uint32_t i = 0; i < textFileLoader.GetLineCount(); ++i)
{
if (!textFileLoader.SplitLineByTab(i, &TokenVector))
continue;
if (TokenVector.size() == 0)
continue;
if (is_number(TokenVector[0]))
{
uint32_t vnum = atoi(TokenVector[0].c_str());
if (vnum > 0)
{
CRaceManager::Instance().RegisterRaceName(vnum, TokenVector[1].c_str());
}
else
{
CRaceManager::Instance().RegisterRaceSrcName(TokenVector[1].c_str(), TokenVector[2].c_str());
}
}
else
{
CRaceManager::Instance().RegisterRaceSrcName(TokenVector[1].c_str(), TokenVector[2].c_str());
}
}
}
Add:
Code:
PyObject * chrmgrLoadNPCList(PyObject* poSelf, PyObject* poArgs)
{
CPythonCharacterManager & rkChrMgr = CPythonCharacterManager::Instance();
rkChrMgr.LoadNPCList();
return Py_BuildNone();;
}
Code:
{ "LoadNPCList", chrmgrLoadNPCList, METH_VARARGS },
Code:
import sys
import app
import dbg
sys.path.append("lib")
class TraceFile:
def write(self, msg):
dbg.Trace(msg)
class TraceErrorFile:
def write(self, msg):
dbg.TraceError(msg)
dbg.RegisterExceptionString(msg)
class LogBoxFile:
def __init__(self):
self.stderrSave = sys.stderr
self.msg = ""
def __del__(self):
self.restore()
def restore(self):
sys.stderr = self.stderrSave
def write(self, msg):
self.msg = self.msg + msg
def show(self):
dbg.LogBox(self.msg,"Error")
sys.stdout = TraceFile()
sys.stderr = TraceErrorFile()
#
# pack file support (must move to system.py, systemrelease.pyc)
#
import marshal
import imp
import VFSImporter
class pack_file_iterator(object):
def __init__(self, packfile):
self.pack_file = packfile
def next(self):
tmp = self.pack_file.readline()
if tmp:
return tmp
raise StopIteration
_chr = __builtins__.chr
class pack_file(object):
def __init__(self, filename, mode = 'rb'):
assert mode in ('r', 'rb')
if not VFSImporter.Exist(filename):
raise IOError, 'No file or directory'
self.data = VFSImporter.Get(filename)
if mode == 'r':
self.data=_chr(10).join(self.data.split(_chr(13)+_chr(10)))
def __iter__(self):
return pack_file_iterator(self)
def read(self, len = None):
if not self.data:
return ''
if len:
tmp = self.data[:len]
self.data = self.data[len:]
return tmp
else:
tmp = self.data
self.data = ''
return tmp
def readline(self):
return self.read(self.data.find(_chr(10))+1)
def readlines(self):
return [x for x in self]
old_open = open
def open(filename, mode = 'rb'):
if VFSImporter.Exist(filename) and mode in ('r', 'rb'):
return pack_file(filename, mode)
else:
return old_open(filename, mode)
__builtins__.open = open
__builtins__.pack_open = pack_open = pack_file
_ModuleType = type(sys)
old_import = __import__
module_do = lambda x:None
def __hybrid_import(name,globals=None,locals=None,fromlist=None, level=-1):
filename = name + '.py'
if VFSImporter.Exist(filename):
if name in sys.modules:
dbg.Tracen('importing from sys.modules %s' % name)
return sys.modules[name]
dbg.Tracen('importing from pack %s' % name)
my_module = VFSImporter.ImportAsModule(filename)
if not my_module:
dbg.TraceError('importing from pack %s failed!' % name)
return my_module
else:
dbg.Tracen('importing from lib %s' % name)
return old_import(name,globals,locals,fromlist, level)
def splitext(p):
root, ext = '', ''
for c in p:
if c in ['/']:
root, ext = root + ext + c, ''
elif c == '.':
if ext:
root, ext = root + ext, c
else:
ext = c
elif ext:
ext = ext + c
else:
root = root + c
return root, ext
def __IsCompiledFile__(sFileName):
sBase, sExt = splitext(sFileName)
sExt=sExt.lower()
if sExt==".pyc" or sExt==".pyo":
return 1
else:
return 0
def __LoadTextFile__(sFileName):
sText=open(sFileName,'r').read()
return compile(sText, sFileName, "exec")
def __LoadCompiledFile__(sFileName):
kFile=open(sFileName)
if kFile.read(4)!=imp.get_magic():
raise
kFile.read(4)
kData=kFile.read()
return marshal.loads(kData)
def execfile(fileName, dict):
if __IsCompiledFile__(fileName):
code=__LoadCompiledFile__(fileName)
else:
code=__LoadTextFile__(fileName)
exec code in dict
import __builtin__
__builtin__.__import__ = __hybrid_import
# cython의 버그로... 외부 모듈의 __dict__를 수정하여, 모듈에 원래 있는 object를 수정해봐야 해당 모듈 내에서 바뀐 object가 적용되지 않는다.
# module_do는 외부 모듈의 execfile object를 __builtin__.execfile에서 system.execfile로 치환하는 작업을 하는데 공염불이다...(외부 모듈은 __builtin__.execfile을 쓸 뿐이다.)
# 따라서 __builtin__.execfile을 system.execfile로 치환해버림...
#module_do = exec_add_module_do
__builtin__.execfile = execfile
def GetExceptionString(excTitle):
(excType, excMsg, excTraceBack)=sys.exc_info()
excText=""
excText+=_chr(10)
import traceback
traceLineList=traceback.extract_tb(excTraceBack)
for traceLine in traceLineList:
if traceLine[3]:
excText+="%s(line:%d) %s - %s" % (traceLine[0], traceLine[1], traceLine[2], traceLine[3])
else:
excText+="%s(line:%d) %s" % (traceLine[0], traceLine[1], traceLine[2])
excText+=_chr(10)
excText+=_chr(10)
excText+="%s - %s:%s" % (excTitle, excType, excMsg)
excText+=_chr(10)
return excText
def ShowException(excTitle):
excText=GetExceptionString(excTitle)
dbg.TraceError(excText)
app.Abort()
return 0
def RunMainScript(name):
try:
execfile(name, __main__.__dict__)
except RuntimeError, msg:
msg = str(msg)
import localeInfo
if localeInfo.error:
msg = localeInfo.error.get(msg, msg)
dbg.LogBox(msg)
app.Abort()
except:
msg = GetExceptionString("Run")
dbg.LogBox(msg)
app.Abort()
import debugInfo
debugInfo.SetDebugMode(__DEBUG__)
loginMark = "-cs"
app.__COMMAND_LINE__ = __COMMAND_LINE__
RunMainScript("prototype.py")
Code:
def __LoadGameNPC():
Code:
def __LoadGameNPC(): chrmgr.LoadNPCList()
:rolleyes: