candyxxf 发表于 2016-4-21 21:04:34

国内某反 系统


该反 系统是某游戏公司的,只是好奇如有得罪,请谅解及联系版主删除!
1,首先是初始化数据,服务器返回第一包,里面包含即将要调用的dll数据和函数名称,目的是让后面的要调用的
代码作前期初始化工作。每个特殊含义的数据,都有自己的ID,后面根据ID进行解析出正确的fuc。

贴上解析数据,并进行数据解析的函数:复制内容到剪贴板代码:
DWORD _CallRetEax(LPBYTE pData)
{      

      DWORD      dwRetEax = 0xFFFFFFFF;
      INT                nPox = 0;
      CHAR*      pRecvBuffer = NULL ;
      INT                nLen;
      RetPoxLen pRetPoxLen;
      INT                n1stType = 0;
      INT                n;
      INT                n1stLen = 0;
      INT                nLastType = 0;
      INT                nTypeID = 0;
      INT                n1stTypeLen = 0;
      INT                n2scTypeLen = 0;
      INT                n2sc = 0;
      INT                nLastSum = 0;
      INT                nLast = 0;
      INT                nLastLen = 0;
      WORD      wInsertId = 0;
      CHAR*      pCallBuffer= NULL;
      DWORD      CallAddr;
      WORD      wFixPox = 0;
      WORD      wFixId = 0;
      WORD      wFindFixId = 0;

      GS_CHECKPTR(pData);
      pRecvBuffer = (CHAR*)(pData);

      nPox = 0;
      nLen = *(WORD*)(pRecvBuffer + nPox);
      nPox += 8;

      pRetPoxLen =_RetLen(pRecvBuffer + nPox);
      nPox += pRetPoxLen.nPox;
      //大类个数
      n1stType = pRetPoxLen.nLen;

      for (n = 0; n < n1stType ; n++)
      {
                nLastLen = 0;

                pRetPoxLen =_RetLen(pRecvBuffer + nPox);
                nPox += pRetPoxLen.nPox;
                //大类长度
                n1stLen = pRetPoxLen.nLen;

                        //大类长度
                        n1stTypeLen = *(WORD*)(pRecvBuffer + nPox);
                        nLastLen +=2;
                        n1stTypeLen -= 2;
                        //ID
                        nTypeID = *(WORD*)(pRecvBuffer + nPox + nLastLen);
                        nLastLen +=2;
                        wInsertId = _FidUseId(nTypeID);
                        if(wInsertId == 0xFFFF)
                        {
                              wInsertId = _FidNoUseId();
                        }
                        m_szRetCall.wId = nTypeID;
                        n1stTypeLen -= 2;
                        //读法类型
                        nLastType = *(WORD*)(pRecvBuffer + nPox + nLastLen);
                        nLastLen +=2;
                        n1stTypeLen -= 2;
                        switch(nLastType)
                        {
                        case 0://读STRING    初始化API名称+数据
                              nPox += nLastLen;
                              memcpy(m_szRetCall.szRetBuffer ,pRecvBuffer + nPox, n1stTypeLen);
                              m_szRetCall.pRetBuffer = m_szRetCall.szRetBuffer;
                              nPox += n1stTypeLen;
                              break;
                        case 1://DWORD+DWORD 初始化API对应关系
                              nPox += nLastLen;
                              m_szRetCall.w1stId = *(WORD*)(pRecvBuffer + nPox);
                              nPox +=2;
                              m_szRetCall.w2secId = *(WORD*)(pRecvBuffer + nPox);
                              nPox +=2;
                              break;
                        case 2://开始执行CALL
                              //nPox += nLastLen;
                              //dwRetEax = _CallBufferId(nTypeID);
                              __logger.Trace("RetEax = %p \n", m_pHook->_dwRetvalue);
                              __logger.Trace("-------------------------------------\n");
                              __logger.Trace("END\n\n");
                              __logger.Fflush();
                              break;
                        default://对CALL开始修正
                              //初始化传过来的API
                              _InitApiDate();
                              //开始修正CALL BUFFER

                              if(nLastLen < nLastType )
                              {
                                        //读出要修正地方的个数
                                        nLastSum = *(WORD*)(pRecvBuffer + nPox + nLastLen);
                                        nLastLen += 2;
                                        n1stTypeLen -= 2;

                                        //循环读出修改的内容
                                        for(nLast = 0; nLast < nLastSum; nLast++)
                                        {
                                                wFixPox = *(WORD*)(pRecvBuffer + nPox + nLastLen);
                                                nLastLen +=2;
                                                wFixId =*(WORD*)(pRecvBuffer + nPox + nLastLen);
                                                nLastLen +=2;
                                                n1stTypeLen -= 4;
                                                //修改CALL BUFFER的API地址
                                                wFindFixId = _FidUseId(wFixId);
                                                if(wFindFixId != 0xFFFF)
                                                {
                                                      //修改为0的地方
                                                      if(m_szRetCall.dwApiAddr != 0)
                                                      {
                                                                if( *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0E8)
                                                                {
                                                                        //CALL XXXXX
                                                                        CallAddr = (DWORD)m_szCallBuffer;
                                                                        *(DWORD*)(pRecvBuffer + nPox + wFixPox) = (DWORD)(m_szRetCall.dwApiAddr - CallAddr -(wFixPox- nLastSum*4 - 8) - 4);
                                                                        __logger.Trace(&quot{:titter:}ox:%p    CALL %s \n",wFixPox- nLastSum*4 - 8, m_szRetCall.w2secId)].szRetBuffer);
                                                                        __logger.Fflush();
                                                                }else if( *(WORD*)(pRecvBuffer + nPox + wFixPox - 2 ) == 0x15FF)
                                                                {
                                                                        //CALL
                                                                        *(DWORD*)(pRecvBuffer + nPox + wFixPox) = (DWORD)&(m_szRetCall.dwApiAddr);
                                                                        __logger.Trace(&quot{:titter:}ox:%p    CALL %s \n",wFixPox- nLastSum*4 - 8, m_szRetCall.w2secId)].szRetBuffer);
                                                                        __logger.Fflush();
                                                                }else if( *(BYTE*)(pRecvBuffer + nPox + wFixPox - 2 ) == 0x8B ||
                                                                              *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0xA1 )
                                                                {
                                                                        //MOV RB32 ,
                                                                        *(DWORD*)(pRecvBuffer + nPox + wFixPox) = (DWORD)&(m_szRetCall.dwApiAddr);
                                                                        __logger.Trace(&quot{:titter:}ox:%p    MOV RB32, %s \n",wFixPox- nLastSum*4 - 8, m_szRetCall.w2secId)].szRetBuffer);
                                                                        __logger.Fflush();
                                                                }else if( *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0B8 ||
                                                                              *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0B9 ||
                                                                                  *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0BA ||
                                                                                  *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0BB ||
                                                                                  *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0BC ||
                                                                                  *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0BD ||
                                                                                  *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0BE ||
                                                                                  *(BYTE*)(pRecvBuffer + nPox + wFixPox - 1 ) == 0x0BF
                                                                                  )
                                                                {
                                                                        //MOV RB32 , XXXXX
                                                                        *(DWORD*)(pRecvBuffer + nPox + wFixPox) = (DWORD)&(m_szRetCall.dwApiAddr);
                                                                        __logger.Trace(&quot{:titter:}ox:%p    MOV RB32, %p = %p \n",wFixPox- nLastSum*4 - 8, m_szRetCall.w2secId)].szRetBuffer);
                                                                        __logger.Fflush();
                                                                }

                                                      }else
                                                      {
                                                                //此为读常量,非API地址的情况 (地址的地址)
                                                                *(DWORD*)(pRecvBuffer + nPox + wFixPox) = (DWORD)&(m_szRetCall.pRetBuffer);
                                                            __logger.Trace(&quot{:titter:}ox:%p    [%p] = %p \n",wFixPox- nLastSum*4 - 8,m_szRetCall.szRetBuffer,*(DWORD*)m_szRetCall.szRetBuffer);
                                                                __logger.Fflush();
                                                      }

                                                }else
                                                {
                                                      __logger.Trace(&quot{:titter:}ox:%p    CALL = %p \n", wFixPox- nLastSum*4 - 8, wFixId);
                                                      __logger.Fflush();
                                                      dwRetEax = 0;
                                                      return dwRetEax;
                                                }
                                                
                                        }
                              }
                              //余下为CALL BUFFER
                              nPox += nLastLen;
                              ZeroMemory(m_szCallBuffer,sizeof(m_szCallBuffer));
                              __logger.Trace("\nCallBufferAddr: %p    CallBufferLen: %p \n\n", &m_szCallBuffer, n1stTypeLen);
                              memcpy(m_szCallBuffer ,pRecvBuffer + nPox, n1stTypeLen);
                              m_szRetCall.pCallBufferAddr = (CHAR*)m_szCallBuffer;
                              nPox += n1stTypeLen;
                              break;
                        }
      }

GS_EXIT:;
      return dwRetEax;
}2,经过上面的解析后,根据数据进行函数初始化复制内容到剪贴板代码:
void _InitApiDate()
{
      HINSTANCE hInstLibrary;
      CHAR*      cDllName;
      CHAR*      cApiName;
      INT                nFindId;

      for(INT i = 0;i <= CALL_BUFFER_NO; i++)
      {
                if( m_szRetCall.wId != 0 &&
                        m_szRetCall.w1stId != 0 &&
                        m_szRetCall.dwApiAddr == 0 &&
                        m_szRetCall.w2secId != 0
                        )
                {
                        nFindId = _FidUseId(m_szRetCall.w1stId);
                        cDllName = m_szRetCall.szRetBuffer;
                        hInstLibrary = LoadLibrary(cDllName);
                        nFindId = _FidUseId(m_szRetCall.w2secId);
                        cApiName = m_szRetCall.szRetBuffer;
                        m_szRetCall.dwApiAddr = (DWORD)GetProcAddress(hInstLibrary,cApiName);
                        FreeLibrary(hInstLibrary);                        
                }
      }
      
      return;
}3,根据
case 2://开始执行CALL
去调用要执行的函数代码复制内容到剪贴板代码:
INT      _CallBufferId(DWORD dwId)
{
      CHAR*      pCallBuffer;
      INT                nRet;
      DWORD      dwFindUseId;
      BOOL      bRetPortect;
      DWORD      dwOldType;

      pCallBuffer = (CHAR*)m_szCallBuffer;
      dwFindUseId = (DWORD)_FidUseId(dwId);
      
      bRetPortect = VirtualProtect(m_szCallBuffer, 8190, PAGE_EXECUTE_READWRITE, &dwOldType);
      
      if(m_szRetCall.pCallBufferAddr != 0)
      {
                __asm
                {
                        pushad
                              pushfd
                                        mov eax, pCallBuffer
                                        call eax
                                        mov nRet, eax
                              popfd
                        popad
                }
      }
               
      bRetPortect = VirtualProtect(m_szCallBuffer, 8190, dwOldType, &dwOldType);

      return nRet;
}这里返回的eax就是反 需要的数据,服务器根据此数据来判断你是否作弊。到此,这反 系统简单流程就是如此了。
专门看了下送来执行的几个函数,发现它们在检查这些数据:
1)代码crc
2)窗体判断
3)hookdll判断
这些都是反 的小功能fuc,当然官方想加什么就加什么,应该非常好diy的,故该游戏的 比较少,也是该系统的功能,
浅析到此为止,如有深入的分析和见解,请发到论坛上来吧

q573923380 发表于 2016-4-21 21:33:11

支持楼主,感谢楼主!

1613436466 发表于 2016-4-22 00:41:01

好贴希望能继续出更多这样的帖子。

奇怪的裤衩 发表于 2016-4-22 02:07:40

好贴希望能继续出更多这样的帖子。

qq46453443 发表于 2016-4-22 04:25:18

真是难得给力的好帖子,回帖鼓励一下

sunj781 发表于 2016-4-22 10:05:58

牛逼的不像人类

sdnx 发表于 2016-4-22 19:29:12

感觉是个好东东,谢谢

dis 发表于 2016-5-5 01:19:23

来试试能不能用吧。。感谢楼主的贡献
页: [1]
查看完整版本: 国内某反 系统