本帖最后由 xingguyuwang 于 2013-02-25 10:05:50 编辑

解决方案 »

  1.   

    ATOM WINAPI RegisterClassA(__in  const WNDCLASSA *lpWndClass)
    {
      WNDCLASSEXA wcex;
      wcex.cbSize = sizeof(WNDCLASSEX);    // 30h
      memcpy(((char *)&wcex) + 4, lpWndClass, sizeof(WNDCLASS));
      wcex.hIconSm = NULL;
      return RegisterClassExWOWA(&wcex, 0, 0, 0x100);
    }
    RegisterClassExWOW就不上图了,直接写出我逆的结果,大家要看码的话,直接把User32.dll拖到IDA看吧。代码:
    HINSTANCE _hmodUser = 0;
    ATOM WINAPI RegisterClassExWOWA(const WNDCLASSEXA *lpWndClassEx, int p2, int p3, int p4)
    {
      if(0 == HIWORD(p3))
      {
        if(lpWndClassEx->cbClsExtra < 0 || lpWndClassEx->cbWndExtra < 0)
        {
          SetLastError(0x57);    // ERROR_INVALID_PARAMETER
          return 0;
        }
        if(_hmodUser == lpWndClassEx->hInstance)
        {
          if(*(int *)(NtCurrentTeb() + 0x6D4) < 0x400)
          {
            SetLastError(0x57);
            return 0;
          }
          if(NULL == lpWndClassEx->hInstance)
          {
            lpWndClassEx->hInstance = GetModuleHandleA(NULL);
          }      int ver;
          if(NULL == lpWndClassEx->hInstance)
          {
            ver = RtlGetExpWinVer(GetModuleHandleA(NULL));
          }
          else
          {
            ver = RtlGetExpWinVer(lpWndClassEx->hInstance);
          }
          if(0x0F7FC0114 == lpWndClassEx->style)
          {
            if(ver > 0x30A)    // Windows版本与样式不符
            {
              SetLastError(0x57);
              return 0;
            }
            lpWndClassEx->style &= 0x803FEEB
          }      if(lpWndClassEx->hbrBackground > 0x1F)    // 小于0x1F的画刷没有Windows版本的限制,都支持
          {
            if(0 == GdiValidateHandle(lpWndClassEx->hbrBackground))    // 无效的
            {
              if(ver > 0x300)
              {
                SetLastError(0x57);
                return 0;
              }
              lpWndClassEx->hbrBackground = 0;
            }
          }      int n;
          HMEMU hMem;
          if(InitClsMemuNameA(&hMem, lpWndClassEx->lpszMenuName, &n))    // 失败
          {
            return 0;
          }      p4 |= 2;
          WNDCLASSEXA wcex;
          memcpy(&wcex, lpWndClassEx, sizeof(WNDCLASSEXA));
          if(ver > 0x30A)
          {
            p4 |= 0x80;
          }
          if(*(char *)(NtCurrentTeb() + 0x6E0) != 2)
          {
            if(GetAppCompatFlags2(0x9900) != 0x800000)
            {
              p4 &= 0xBFFFFFFF;
            }
          }
          if(int((p4 << 8) >> 24) != 1)
          {
            int x;
            if(NULL == ClassNameToVersion(lpWndClassEx->lpszClassName, &x, 0, 1))
            {
              ver = 0;
              // 从 loc_77D1A552 开始下面的流程是根据临时指针变量是否为NULL来释放资源
              if([ebp+var_138] == 0)    // [ebp+var_138]在函数入口处确实被赋值为0
              {
                RtlFreeHeap(NULL, 0, 0);
              }
              // ...
              return ver;
            }
            else
            {
              // 调用NtUserRegisterClassExWOW
              // NtUserRegisterClassExWOW进入系统调用,调用号11E8h
            }
          }
        }
        else
        {
          // lpWndClassEx->hInstance有值
        }
      }
      else
      {  }
    }
    NtUserRegisterClassExWOW部分比较简单是直接进行系统调用看样子,如果instance为NULL。这个函数自己会取一个instance.
      

  2.   

    下面代码应该是你所说的。
    能不能输入别的应用程序的hInstance?     if(NULL == lpWndClassEx->hInstance)
          {
            lpWndClassEx->hInstance = GetModuleHandleA(NULL);
          }