最近在写一个有关自动交易的外挂。在不使用外挂时,程序的流程是这样的,当客户A提出与客户B交易请求时,客户B会在界面上弹出一个对话框,里面说明了 XXXX希望和你交易,客户B确认以后进入交易界面。在界面里会列出需要交易的物品数量名称等,同时客户A也能看到客户B的交易物品。双方各取所需后确认交易。
外挂需要完成的工作是自动交易,也就是当客户A发出请求后,客户B自动获取客户A 的名称已经其提供交易的物品名称和数量,外挂记录下对方的ID已经本次双方交易物品的名称和数量。
由于程序是基于.NET的,用OLLYDBG无法跟踪,一打开程序就自动停在 INT3, MSCORWKS.7A012AA0。
采用CHEAT ENGINE在程序运行后再利用搜索和定位(findout where to write this address)则可以看到相应的指令代码。
因此思路如下,首先当进入交易时通过搜索找到交易品的数量动态地址(ADDR1),然后找出写这个数量的语句(SRC语句),外挂程序动态在交易程序地址空间申请一块地址,将SRC语句地址处置入JMP ADDR1,在ADDR1处将交易数量的值写入刚才申请的地址空间中的一个相对固定的地址(addr2).然后执行SRC语句,再跳回原来的SRC语句下面的语句处。这样动态的交易数量就被移动当相对固定的地址ADDR2中,外挂程序只需通过ReadProcessMemory即可获得交易数量。这个思路用的关键函数如下:
1。申请动态地址空间
LPVOID AllocMemory(DWORD pid,int len)
{
LPVOID pMem;
BYTE *pBuf;
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE,FALSE,pid);
if (hProcess==NULL)
return NULL;
pMem = ::VirtualAllocEx(hProcess, NULL, len, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//清零,可以不要似乎
pBuf = new BYTE[len];
::ZeroMemory(pBuf,len);
WriteMemory(pid, (ULONG)pMem,pBuf,len);
CloseHandle(hProcess);
return pMem;
}
2. 写地址空间
int WriteMemory(DWORD pid, ULONG addr, BYTE *buf, int len)
{
ULONG nByteWrited;
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE,FALSE,pid);
if (hProcess==NULL)
return -1;
BOOL nOK=WriteProcessMemory(hProcess, (LPVOID)addr, buf,len,&nByteWrited);
if (!nOK)
return -2;
if (nByteWrited!=len)
return -3;
CloseHandle(hProcess);
return 1;
}
3.读取内存空间
int ReadMemoryInt(DWORD pid, ULONG addr, int len, int *ret)
{
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ|
PROCESS_VM_WRITE,FALSE,pid);
if (hProcess==NULL)
return -1;
switch (len)
{
BYTE byte;
SHORT ss;
int ww;
case 1:
if (!ReadProcessMemory(hProcess, (LPVOID)addr, &byte,len,NULL))
{
CloseHandle(hProcess);
return -1;
}
*ret=byte;
break;
case 2:
if (!ReadProcessMemory(hProcess, (LPVOID)addr, &ss,len,NULL))
{
CloseHandle(hProcess);
return -1;
}
*ret=ss;
break;
case 4:
if (!ReadProcessMemory(hProcess, (LPVOID)addr, &ww,len,NULL))
{
CloseHandle(hProcess);
return -1;
}
*ret=ww;
break;
default:
CloseHandle(hProcess);
return -1;
}
CloseHandle(hProcess);
return 1;
}
在处理动态数字量的时候这个程序工作的很好,但问题是如何找到客户名或交易物品的名字?数值量可以通过在进入交易界面后不断修改被交易物品的数量,然后用CE多次的SEARCH来找到,但是对于字符串则这个思路不行了,因为当客户B看到客户A的请求以后该名字串已经被写入某一动态地址,虽然可以找到其位置但无法找到写入语句的位置。本人是新手,希望这里的高手能提供一个思路。万分感谢!
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)