QQGame Analysis Series-you can also split multiple halls
Title: [original] QQGame Analysis Series-you can also split the multi-open Hall
Author: singsing
Time: 2008-04-: 57
Chain: http://bbs.pediy.com/showthread.php? T = 63266
QQGame Analysis Series (1)-You can also split multiple halls
This series is intended only for learning, communication, and illegal users.
Recently, When I was bored, I lost my friends and played cards together. It was a QQ game landlords game. We usually played cards at a Table, which increased the odds. once he was playing cards with others, and when the four were full, I couldn't play with him. I just clicked and found that I could enter the table. The game provided the "watching" function, it was only known at the time. so I "watched" other people's cards one by one and told my friends the cards. He was "strategizing, winning a thousand miles", huh, huh ....
So I came up with a "bad idea": I played two cards on my own, one for watching, and the other for playing cards. Isn't it easy to win? When I was excited about preparing for "tricks", I found that QQGame could not run two instances at the same time, so my above ideas cannot be implemented for the moment. to achieve this, we need to break through this level, so we will try to analyze the principle that "QQGame cannot run two instances at the same time.
The principle that a program can run only one instance is that mutex, critical section, semaphore, and other mechanisms are usually used.
Therefore, the OD is loaded and disconnected:
Bp CreateMutexA
F9 running, interrupted, again f9...... several times later, you will see the stack prompt:
0013FE90 100118DF/CALL to CreateMutexA from Utility.100118D9
0013FE94 00000000 | pSecurity = NULL
0013FE98 00000001 | InitialOwner = TRUE
0013FE9C 00F88700 MutexName = "QQGame_Mutex03/01/2003"
What we care about is MutexName "QQGame_Mutex03/01/2003.
If you know this, it is easy to bypass "QQGame cannot run two instances at the same time". Here I am using the principle of not damaging the integrity of the original program.
Is introduced as follows:
The MutexName is "QQGame_Mutex03/01/2003" string is stored in a string called MainLogi. dll file, in the Logic folder under the game installation directory. if the MutexName of each game program is different from that of the previous one, can it be bypassed? That is, before each program is run, the MutexName in the MainLogi. dll file is secretly changed. For details, see the code and analysis:
Program QQgameSpy;
Uses
Windows, dialogs, sysutils, classes, graphics, shellapi, registry;
Var
Reg: TRegistry;
StrPath: string;
StrFileName: string;
StrNewFile: string;
StrGameFile: string;
StrMutex: string;
I: integer;
HMutex: DWORD;
HFile: DWORD;
DwBytesOfRW: Cardinal;
Buffer: BYTE;
DstFile: TFileStream;
Hwnd: DWORD;
{$ R QQgameSpy. RES}
Function RenameFile (hdl: THandle; lpOrgName, lpNewName: PAnsichar): boolean;
Var
Shf: TSHFILEOPSTRUCT;
Begin
Try
FillChar (shf, SizeOf (shf), 0 );
Shf. Wnd: = hdl;
Shf. wFunc: = FO_RENAME;
Shf. pFrom: = lpOrgName;
Shf. pTo: = lpNewName;
Shf. fFlags: = FOF_NOCONFIRMATION + FOF_SILENT;
Result: = (0 = SHFileOperation (shf ));
Except
Result: = false;
End;
End;
{Main program start}
Begin
Reg: = TRegistry. Create;
Reg. RootKey: = HKEY_CURRENT_USER;
If reg. OpenKeyReadOnly (SoftwareTencentQQGameSYS) = false then
Exit;
StrPath: = reg. ReadString (GameDirectory );
// Showmessage (strPath );
Reg. CloseKey;
Reg. Free;
StrFileName: = strPath + LogicMainLogi. dll;
StrMutex: = QQGame_Mutex03/01/2000;
For I: = 0 to 3 do begin
HMutex: = CreateMutex (nil, false, pchar (strMutex ));
If hMutex = 0 then
Continue;
If GetLastError <> ERROR_ALREADY_EXISTS then
Break;
Inc (strMutex [Length (strMutex)]);
End;
// Showmessage (strMutex );
Buffer: = BYTE (strMutex [Length (strMutex)]);
If hMutex = 0 then
Exit;
CloseHandle (hMutex );
// DstFile: = TFileStream. Create (strFileName, fmOpenReadWrite );
// DstFile. Seek ($581C1, FILE_BEGIN );
// DstFile. WriteBuffer (buffer, sizeof (buffer ));
For I: = 0 to 2 do begin
StrNewFile: = strFileName + inttostr (I );
DeleteFile (strNewFile );
End;
For I: = 0 to 2 do begin
StrNewFile: = strFileName + inttostr (I );
If FileExists (strNewFile) = false then
Break;
End;
RenameFile (0, pchar (strFileName), pchar (strNewFile ));
CopyFile (pchar (strNewFile), pchar (strFileName), true );
HFile: = CreateFile (pchar (strFileName), GENERIC_WRITE or GENERIC_READ, file_1__write or file_1__read,
Nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
If hFile = INVALID_HANDLE_VALUE then
Exit;
SetFilePointer (hFile, $581C1, nil, FILE_BEGIN );
& N