Jump to content

Neo2003

Members
  • Posts

    149
  • Joined

  • Last visited

  • Donations

    0.00 GBP 

Posts posted by Neo2003

  1. Hello,

    Just for your information, I try to break some RC4 keys of modules for which I did not get it via sniffing. In fact I did get them from wdb.

    But even if I manage to brute force 700 000 key test per second on a single process/single thread, it's not possible to get the 128bits key in a reasonable time.

    If you know any shortcut to brute force a RC4 key, I would be happy to hear it.

    I already only recrypt the 1st 6 bytes of the module to check the uint32 module_deflated_size in a proper range and the uint16 zlib signature. Then if this pass, I decrypt the module until the RSA signature to check the "SIGN" at offset size-0x104 (I never came to that point yet on an unknown module, so my first check with 6 bytes is pretty well).

    I also changed a bit the rc4 function to write the result in another buffer to prevent the memory copy each loop. Here is the code, if you see any big optimization, tell me ;)

    #include <windows.h>
    #include <stdio.h>
    #include <time.h>
    #include <stdint.h>
    #include "BigNumber.h"
    
    // rc4 part
    inline void SWAP(uint8_t *a, uint8_t *b);
    inline void rc4_init(uint8_t *key_buffer, uint8_t *base, uint32_t base_length);
    inline void rc4_crypt(uint8_t *key, uint8_t *data, uint32_t length, uint8_t *destdata);
    
    int main(int argc, char *argv[])
    {
       uint32_t mod_length = 18754;
       char *name = "1D811DBA8199D4CF0633CE36C7557E3D.bin";
    
       FILE *fp = fopen(name, "rb");
       if(!fp)
       {
           printf("Module file missing!!!\\n");
           return 0;
       }
    
       uint8_t *m_cryptedModule, *m_workCopy;
       m_cryptedModule = (uint8_t*)malloc(sizeof(uint8_t)*mod_length);
       m_workCopy      = (uint8_t*)malloc(sizeof(uint8_t)*(mod_length - 0x100));
       uint8_t m_testKey[0x102];
    
       fread(m_cryptedModule, sizeof(uint8_t)*mod_length, 1, fp);
       fclose(fp);
    
       BigNumber bn;
       bn.SetDword(0);
       bool found = false;
    
       time_t start = time(0);
       uint32_t a = -1;
       while (!found)
       {
           if (0x007FFFFF == a++)
           {
               a = 0;
               printf("%u: ", time(0) - start);
               printf("%s\\n", bn.AsHexStr());
           }
           // fast check
           rc4_init(m_testKey, bn.AsByteArray(16, false), 16);
           rc4_crypt(m_testKey, m_cryptedModule, 6, m_workCopy); // no need to decrypt until the end
           uint32_t m_inflatedSize = *(uint32_t*)m_workCopy;
           uint16_t m_sign = *(uint16_t*)(m_workCopy+4);
           if (m_sign == 0xDA78 && m_inflatedSize > 25500 && m_inflatedSize < 34500)  // 78 DA
           {
               printf("%s: slib signature check pass.\\n    Inflated size would be %u\\n", bn.AsHexStr(), *(uint32_t*)m_workCopy);
               rc4_init(m_testKey, bn.AsByteArray(16, false), 16);
               rc4_crypt(m_testKey, m_cryptedModule, mod_length - 0x100, m_workCopy); // no need to decrypt until the end
               uint32_t m_signature = *(uint32_t*)(m_workCopy + mod_length - 0x104);
               if (m_signature == 0x5349474E)
               {
                   printf("Found !!!!!!\\n");
                   fp = fopen("module.key", "wb");
                   fwrite(&mod_length, sizeof(uint32_t), 1, fp);
                   fwrite(bn.AsByteArray(16, false), sizeof(uint8_t)*16, 1, fp);
                   fclose(fp);
                   found = true;
                   printf("\\n%s - 0x%08X\\n", bn.AsHexStr(), m_signature);
               }
           }
           ++bn;
       }
       return 0;
    }
    
    // rc4 part
    inline void SWAP(uint8_t *a, uint8_t *b)
    {
       uint8_t t;
       t = *a;
       *a = *b;
       *b = t;
    }
    
    inline void rc4_init(uint8_t *key_buffer, uint8_t *base, uint32_t base_length)
    {
       uint8_t val = 0;
       uint32_t position = 0;
       uint32_t i;
    
       for(i = 0; i < 0x100; i++)
           key_buffer[i] = (uint8_t)i;
    
       key_buffer[0x100] = 0;
       key_buffer[0x101] = 0;
    
       for(i = 1; i <= 0x40; i++)
       {
           val += key_buffer[(i * 4) - 4] + base[position++ % base_length];
           SWAP(&key_buffer[(i * 4) - 4], &key_buffer[val & 0x0FF]);
    
           val += key_buffer[(i * 4) - 3] + base[position++ % base_length];
           SWAP(&key_buffer[(i * 4) - 3], &key_buffer[val & 0x0FF]);
    
           val += key_buffer[(i * 4) - 2] + base[position++ % base_length];
           SWAP(&key_buffer[(i * 4) - 2], &key_buffer[val & 0x0FF]);
    
           val += key_buffer[(i * 4) - 1] + base[position++ % base_length];
           SWAP(&key_buffer[(i * 4) - 1], &key_buffer[val & 0x0FF]);
       }
    }
    
    inline void rc4_crypt(uint8_t *key, uint8_t *data, uint32_t length, uint8_t *destdata)
    {
       for(uint32_t i = 0; i < length; i++)
       {
           key[0x100]++;
           key[0x101] += key[key[0x100]];
           SWAP(&key[key[0x101]], &key[key[0x100]]);
           //data[i] ^= key[(key[key[0x101]] + key[key[0x100]]) & 0x0FF];
           destdata[i] = data[i] ^ (key[(key[key[0x101]] + key[key[0x100]]) & 0x0FF]);
       }
    }
    

    I did add ++ and -- operators to BigNumber class like this:

    BigNumber BigNumber::operator++()
    {
       BN_add_word(_bn, 1);
       return *this;
    }

  2. For 2.4.3, you only need to change void WardenMgr::SendWardenData(WorldSession* const session) method in WardenMgr.cpp line 882-929. The modules are unchanged and the keys are the same since they are associated with the module.

    This method send to the client the offsets of the functions in Warden Client (in wow.exe). I did comment them, the first group are the MPQ access functions, then LUA functions and finally the PerformanceCounter for timing check which did not exist by default in 3.3.5 sniffs.

    I will dig my hard-disk next week, I probably have the packet somewhere for 2.4.3.

    The patch can work for 2.4.3, but it won't work for 1.12 since the modules format was different in Vanilia, then keys were different too.

  3. where did the *.key file come from?

    *.bin file I think is download from official server.

    It seems that *.bin file is a dll file. Can I write my check mod by myself?

    The *.key are generated from packet sniff.

    The .bin are also get from sniffing, but can be taken from wowcache.wdb. Anyway a module is useless without the RC4 key to decode it (.key file).

    You can create your own module but the client will never load it. The last 2048 bits of the .bin are the RSA signature of it. As for the redirect packet, it's not possible at this point of the time to break such an encryption and it's a good thing or anyone could send harmful code to the client.

  4. I spent 2 days checking everything, I will let this ACE problem to an ACE expert, I cannot debug this ____ myself.

    I think the best reactor to use on Linux is the default one : ACE_Select_Reactor, then we don't even need any #ifdef. On Windows, there is no problem, the "WFMO" is working fine on Windows, while the "Select" one on Linux fails the run_reactor_event_loot().

    I tried to instantiate a reactor out of the ACE_Reactor::instance() singleton, this changes nothing.

    I rewrote the WardenSvcHandler class so that method are matching 100% the base ACE_Svc_Handler class, this changes nothing.

    I am out of idea. I don't understand why on Linux ACE works so bad.

  5. Crash if run not in wow dir.

    The second link I posted fixed this.

    But more bad news. For me fail patch 4.1.0 exe :(((

    Addition info: C# version also fail patch. So tool required offset or more deep updates :((

    I have same problem, unable to patch neither wow.exe 4.0.3, nor 4.1.0. Only wow.exe 4.0.6 patches properly.

  6. The problem is around ACE and the Reactor used for Linux. I was not yet able to find a working one on Linux while the Windows one (WFMO_Reactor) just works fine.

    If I use a TP_Reactor or a DEV_POL_Reactor, I get this problem of infinite loop, if I use the Select_Reactor, I cannot get data back from core, the handle_input method is simply never called.

    I am still searching how to make this damn Select_Reactor work on Linux.

  7. I don't really agree XTZ

    Initializing a const std::vector is a pain in C++

    I would have to do either:

    const std::vector<byte> replace(5);
    replace[0] = 
    replace[1] = 
    ...

    or I would have to overload some std::vector operator to fill it anyway with an array, so a time lost for me and the application ;)

    And all this just to remove the arrays length I have to pass arguments to the methods.

  8. Just for information, this problem was fixed in [11398], [s1157] and in [z1590].

    While we don't provide support for CMake on Windows, I currently work a bit on this part to at least make it work properly.

    You also can use the -DPREFIX=SomePath to CMake so that files are put where you want when you compile the "INSTALL" project.

  9. i just looked at the line which is being reported on your screenshot and it doesn't give me this error because i'm using x64 and you're using x86. it tries to use ${WIN_DEBUGLIBS} which is never being set (at least neither in ./CMakeLists.txt nor in ./src/realmd/CMakeLists.txt)

    Hehe. This problem is your fault :)

    https://github.com/mangos/mangos/commit/d88b5eedb8ec9e7a1de2c3d4880489bf2894a5a0

    Drop the lines " debug ${WIN_DEBUGLIBS}" in src/realmd/CMakeLists.txt and src/mangosd/CMakeLists.txt and the problem is fixed.

  10. PSS:

    infinite loop in WardenMgr::Update

    http://pastebin.com/3At5xDhr

    I get this too.

    Mee too :S

    Found what could cause this but not why yet.

    Mangosd did receive a packet from Wardend which is not understood, so skipping 2 uint8 per second is low and makes like a freeze.

    Moreover, I added a BanLength option in config in days. 0 = infinite else the number of days.

    I will post a new version soon when I know better what could cause an invalid packet from Wardend. Maybe try to change the port used. 4321 may be used for something else so try something higher. I will move to port 6555 in next patch by default.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use