Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 10-05-2020, 20:23
dion dion is offline
game tech
 
Join Date: Jan 2002
Posts: 161
Rept. Given: 12
Rept. Rcvd 2 Times in 2 Posts
Thanks Given: 4
Thanks Rcvd at 4 Times in 4 Posts
dion Reputation: 2
Need help identifying modified blowfish algo

Hello,

i am working on an arm linux elf file that has blowfish encryption algorithm inside. But whatever i did to reproduce them, i can't get the same results. this is what it's like in decompiled form.

Code:
unsigned int __fastcall CBlowFish::Encode(CBlowFish *this, unsigned __int8 *a2, unsigned __int8 *a3, unsigned int a4)

{
  v4 = a3;
  v26 = a2;
  v23 = a4;
  v25 = this;
  v5 = CBlowFish::GetOutputLength(this, a4);
  v6 = v5;
  if ( v5 )
  {
    v7 = 0;
    v8 = v23;
    v9 = (unsigned int *)v4;
    v10 = (unsigned int *)v26;
    v24 = v23 - 7;
    v22 = v5 - v23;
    do
    {
      if ( v26 == v4 )
      {
        if ( v7 >= v24 )
        {
          v11 = (char *)v10 + v23;
          if ( v22 > 0 )
          {
            v12 = (int)&v11[v22];
            do
              *v11++ = 0;
            while ( v11 != (_BYTE *)v12 );
          }
        }
        v13 = v10;
        v14 = v10 + 1;
        v10 += 2;
        CBlowFish::Blowfish_encipher(v25, v13, v14);
        goto LABEL_9;
      }
      if ( v7 >= v24 )
      {
        v17 = v8;
        if ( v8 <= 0 )
        {
          v21 = (int)v9;
          v17 = 0;
        }
        else
        {
          v18 = 0;
          do
          {
            *((_BYTE *)v9 + v18) = *((_BYTE *)v10 + v18);
            ++v18;
          }
          while ( v8 != v18 );
          v21 = (int)v9 + v8;
          v10 = (unsigned int *)((char *)v10 + v8);
          if ( v8 > 7 )
            goto LABEL_14;
        }
        v19 = v21 - v17;
        v20 = v17;
        do
          *(_BYTE *)(v19 + v20++) = 0;
        while ( v20 <= 7 );
      }
      else
      {
        v16 = 0;
        do
        {
          *((_BYTE *)v9 + v16) = *((_BYTE *)v10 + v16);
          ++v16;
        }
        while ( v16 != 8 );
      }
LABEL_14:
      v10 += 2;
      CBlowFish::Blowfish_encipher(v25, v9, v9 + 1);
      v9 += 2;
LABEL_9:
      v7 += 8;
      v8 -= 8;
    }
    while ( v6 > v7 );
  }
  return v6;
Code:
int __fastcall CBlowFish::Blowfish_encipher(CBlowFish *this, unsigned int *a2, unsigned int *a3)

 v3 = *(_DWORD **)this;
  v4 = *((_DWORD *)this + 1);
  v5 = *a2 ^ **(_DWORD **)this;
  v6 = *(_DWORD *)(*(_DWORD *)this + 20);
  v7 = *a3 ^ (((*(_DWORD *)(v4 + 4 * ((v5 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v5 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v5 >> 8) + 2048))
            + *(_DWORD *)(v4 + 4 * (unsigned __int8)v5 + 3072)) ^ *(_DWORD *)(*(_DWORD *)this + 4);
  v8 = *(_DWORD *)(*(_DWORD *)this + 24);
  v9 = v5 ^ (((*(_DWORD *)(v4 + 4 * ((v7 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v7 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v7 >> 8) + 2048))
           + *(_DWORD *)(v4 + 4 * (unsigned __int8)v7 + 3072));
  v10 = *(_DWORD *)(*(_DWORD *)this + 32);
  v11 = v9 ^ *(_DWORD *)(*(_DWORD *)this + 8);
  v12 = *(_DWORD *)(*(_DWORD *)this + 28);
  v13 = *(_DWORD *)(*(_DWORD *)this + 36);
  v14 = *(_DWORD *)(*(_DWORD *)this + 40);
  v15 = *(_DWORD *)(*(_DWORD *)this + 44);
  v16 = (((*(_DWORD *)(v4 + 4 * ((v11 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v11 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v11 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v11 + 3072)) ^ *(_DWORD *)(*(_DWORD *)this + 12) ^ v7;
  v17 = v3[17];
  v18 = (((*(_DWORD *)(v4 + 4 * ((v16 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v16 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v16 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v16 + 3072)) ^ v3[4] ^ v11;
  v19 = v3[16];
  v20 = (((*(_DWORD *)(v4 + 4 * ((v18 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v18 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v18 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v18 + 3072)) ^ v6 ^ v16;
  v21 = (((*(_DWORD *)(v4 + 4 * ((v20 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v20 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v20 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v20 + 3072)) ^ v8 ^ v18;
  v22 = (((*(_DWORD *)(v4 + 4 * ((v21 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v21 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v21 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v21 + 3072)) ^ v12 ^ v20;
  v23 = (((*(_DWORD *)(v4 + 4 * ((v22 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v22 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v22 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v22 + 3072)) ^ v10 ^ v21;
  v24 = (((*(_DWORD *)(v4 + 4 * ((v23 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v23 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v23 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v23 + 3072)) ^ v13 ^ v22;
  v25 = (((*(_DWORD *)(v4 + 4 * ((v24 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v24 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v24 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v24 + 3072)) ^ v14 ^ v23;
  v26 = (((*(_DWORD *)(v4 + 4 * ((v25 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v25 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v25 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v25 + 3072)) ^ v15 ^ v24;
  v27 = (((*(_DWORD *)(v4 + 4 * ((v26 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v26 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v26 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v26 + 3072)) ^ v3[12] ^ v25;
  v28 = (((*(_DWORD *)(v4 + 4 * ((v27 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v27 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v27 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v27 + 3072)) ^ v3[13] ^ v26;
  v29 = (((*(_DWORD *)(v4 + 4 * ((v28 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v28 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v28 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v28 + 3072)) ^ v3[14] ^ v27;
  v30 = (((*(_DWORD *)(v4 + 4 * ((v29 >> 16) & 0xFF) + 1024) + *(_DWORD *)(v4 + 4 * (v29 >> 24))) ^ *(_DWORD *)(v4 + 4 * ((unsigned __int16)v29 >> 8) + 2048))
       + *(_DWORD *)(v4 + 4 * (unsigned __int8)v29 + 3072)) ^ v3[15] ^ v28;
  v31 = v4 + 4 * ((unsigned __int16)v30 >> 8);
  v32 = *(_DWORD *)(v4 + 4 * (v30 >> 24));
  v33 = v4 + 4 * (unsigned __int8)v30;
  v34 = *(_DWORD *)(v4 + 4 * ((v30 >> 16) & 0xFF) + 1024);
  result = v30 ^ v17;
  *a3 = (((v34 + v32) ^ *(_DWORD *)(v31 + 2048)) + *(_DWORD *)(v33 + 3072)) ^ v19 ^ v29;
  *a2 = result;
  return result;
i upload the elf file here in case someone interested.
hxxps://filebin.net/yordbkvlpmofbaem

thanks in advance
Reply With Quote
  #2  
Old 10-06-2020, 20:00
ionioni ionioni is online now
Friend
 
Join Date: Jul 2016
Posts: 50
Rept. Given: 0
Rept. Rcvd 3 Times in 3 Posts
Thanks Given: 36
Thanks Rcvd at 56 Times in 28 Posts
ionioni Reputation: 3
upper function std::string *__fastcall linx::LCEncryption::EncryptDecrypt(std::string *pStrOutput, const char **ppInput, int mode)
Code:
v7 = lenInput % 8;
if ( lenInput % 8 )
  v7 = 8 - v7;
lSize = lenInput + v7;
v9 = lenInput + v7 + 1;
pInput = operator new[](v9);
memset(pInput, 0, v9);
strcpy(pInput, *ppInput);
CBlowFish::CBlowFish();
BYTE key[2] = {0};
CBlowFish::Initialize(key, 2);//???              
if (mode)
{
  pOutput = operator new[](2 * lSize);
  memset(pOutput, 0, 2 * lSize);
  CBlowFish::Encode(pInput, pOutput, lSize);
  bits = (8 * lSize);
  lenBase32Str = linx::LCBase32::toLen(bits);
  Base32Str = operator new[](lenBase32Str);
  memset(Base32Str, 0, lenBase32Str);
  linx::LCBase32::toBaseStr(Base32Str, lenBase32Str, pOutput, bits);
  v24 = strlen(Base32Str);
  std::string::assign(pStrOutput, Base32Str, v24);
}
Looks like standard BF, in encryption mode (arg3 mode !0) takes a string as arg2 and returns a base32 of the encoded BF as arg1, I've also checked the random digit tables from the a binary and they're identical to the standard BF (for eg. this)

Maybe if you can show some sample pairs of input/output strings to LCEncryption::EncryptDecrypt

I don't have the proper arm env to debug the exe, tried it in qemu but it cries for missing so libs and some (QT) are compiled for this embedded app (ie not something that can be googled for) maybe if you can make a rootfs of the env or don't know, do a find / -name \*.so and only pack those (you have at least read access because of the a binary)

Last edited by ionioni; 10-06-2020 at 21:04.
Reply With Quote
  #3  
Old 10-06-2020, 21:31
dion dion is offline
game tech
 
Join Date: Jan 2002
Posts: 161
Rept. Given: 12
Rept. Rcvd 2 Times in 2 Posts
Thanks Given: 4
Thanks Rcvd at 4 Times in 4 Posts
dion Reputation: 2
i am new in reversing arm binaries. but, i don't think running that big elf file would be any use. or maybe qemu has debug capability?

been trying to setup qemu as ida debugger but it just hangs at start up. and there's really little information about this (ida and qemu) in the web.

Quote:
Looks like standard BF, in encryption mode (arg3 mode !0) takes a string as arg2 and returns a base32 of the encoded BF as arg1, I've also checked the random digit tables from the a binary and they're identical to the standard BF (for eg. this)
have known about the tables. but warn you, the base32 is custom one, not standard base32. which might be where i failed to reproduce...

Quote:
Maybe if you can show some sample pairs of input/output strings to LCEncryption::EncryptDecrypt
what i have is i believed not for this function, but for LCUserManager::CheckPassword. There is only one pair.
1824781686.png

Quote:
I don't have the proper arm env to debug the exe, tried it in qemu but it cries for missing so libs and some (QT) are compiled for this embedded app (ie not something that can be googled for) maybe if you can make a rootfs of the env or don't know, do a find / -name \*.so and only pack those (you have at least read access because of the a binary)
i have actually something else in my mind, it is to just "stitch" those functions into a somekind pre-conditioned hello world app compiled for arm. does it sounds right? i mean achieveable?

thanks

Last edited by dion; 10-06-2020 at 21:47.
Reply With Quote
  #4  
Old 10-06-2020, 21:51
ionioni ionioni is online now
Friend
 
Join Date: Jul 2016
Posts: 50
Rept. Given: 0
Rept. Rcvd 3 Times in 3 Posts
Thanks Given: 36
Thanks Rcvd at 56 Times in 28 Posts
ionioni Reputation: 3
Quote:
check pm.
don't think PM works for my user group

Last edited by ionioni; 10-07-2020 at 03:01.
Reply With Quote
  #5  
Old 10-10-2020, 04:13
sh3dow sh3dow is offline
Family
 
Join Date: Oct 2014
Posts: 94
Rept. Given: 94
Rept. Rcvd 77 Times in 22 Posts
Thanks Given: 230
Thanks Rcvd at 107 Times in 40 Posts
sh3dow Reputation: 77
Quote:
been trying to setup qemu as ida debugger but it just hangs at start up. and there's really little information about this (ida and qemu) in the web.

Try Azeria Labs VM
https://azeria-labs.com/arm-lab-vm/
https://azeria-labs.com/lab-vm-2-0/
https://azeria-labs.com/emulating-arm-firmware/

Or Hugsy (the creator of GEF) VM labs
https://blahcat.github.io/2017/06/25/qemu-images-to-play-with/
Reply With Quote
The Following 2 Users Say Thank You to sh3dow For This Useful Post:
dion (10-10-2020), niculaita (10-10-2020)
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



All times are GMT +8. The time now is 19:43.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX
( 1998 - 2020 )