카카오톡 악성코드가 사용하는 so 파일 분석중
RIJNDAEL-192 + XOR 암호화 / 복호화 루틴을 찾아내서
복원스크립트를 만들어봄...
import rijndael
import base64
import os, sys
KEY_SIZE = 16
BLOCK_SIZE = 24
def encrypt(key, plaintext):
padded_key = key.ljust(KEY_SIZE, '\0')
padded_text = plaintext + (BLOCK_SIZE - len(plaintext) % BLOCK_SIZE) * '\0'
# could also be one of
#if len(plaintext) % BLOCK_SIZE != 0:
# padded_text = plaintext.ljust((len(plaintext) / BLOCK_SIZE) + 1 * BLOCKSIZE), '\0')
# -OR-
#padded_text = plaintext.ljust((len(plaintext) + (BLOCK_SIZE - len(plaintext) % BLOCK_SIZE)), '\0')
r = rijndael.rijndael(padded_key, BLOCK_SIZE)
ciphertext = ''
for start in range(0, len(padded_text), BLOCK_SIZE):
ciphertext += r.encrypt(padded_text[start:start+BLOCK_SIZE])
encoded = base64.b64encode(ciphertext)
return encoded
def decrypt(key, encoded):
padded_key = key.ljust(KEY_SIZE, '\0')
ciphertext = base64.b64decode(encoded)
r = rijndael.rijndael(padded_key, BLOCK_SIZE)
padded_text = ''
for start in range(0, len(ciphertext), BLOCK_SIZE):
padded_text += r.decrypt(ciphertext[start:start+BLOCK_SIZE])
plaintext = padded_text.split('\x00', 1)[0]
return plaintext
def xor(string, key):
res=''
for c in string:
res += chr(ord(c) ^ ord(key))
return res
cipher = sys.argv[1]
d1 = decrypt( cipher[2:10], cipher[10:] )
print xor(d1, chr(ord(cipher[0]) ^ 0x0a) )
... 분석 디컴파일소스중 일부
int __fastcall my_decrypt(int a1, int str_in)
{
int str_in_; // r6@1
int result; // r0@3
void *v4; // r10@5
void *v5; // r7@6
void *v6; // r8@9
int cipher_ctx; // r8@12
void *key; // r11@17
int v9; // r3@18
int output; // [sp+4h] [bp-D4h]@1
void *ptr; // [sp+Ch] [bp-CCh]@28
unsigned int n; // [sp+10h] [bp-C8h]@24
unsigned __int8 v13; // [sp+1Ch] [bp-BCh]@21
int v14; // [sp+24h] [bp-B4h]@34
const void *v15; // [sp+28h] [bp-B0h]@31
char v16; // [sp+2Ch] [bp-ACh]@24
const void *v17; // [sp+30h] [bp-A8h]@24
int v18; // [sp+34h] [bp-A4h]@21
void *src; // [sp+38h] [bp-A0h]@13
int v20; // [sp+3Ch] [bp-9Ch]@5
int v21; // [sp+40h] [bp-98h]@5
int v22; // [sp+44h] [bp-94h]@5
int ECB_mode; // [sp+48h] [bp-90h]@1
char v24; // [sp+58h] [bp-80h]@16
char v25; // [sp+5Ch] [bp-7Ch]@34
char v26; // [sp+64h] [bp-74h]@32
char v27; // [sp+68h] [bp-70h]@29
char v28; // [sp+6Ch] [bp-6Ch]@25
char v29; // [sp+70h] [bp-68h]@22
char v30; // [sp+74h] [bp-64h]@27
char v31; // [sp+78h] [bp-60h]@14
char v32; // [sp+7Ch] [bp-5Ch]@8
char v33; // [sp+80h] [bp-58h]@5
char v34; // [sp+84h] [bp-54h]@5
char v35; // [sp+88h] [bp-50h]@2
int algo_name; // [sp+8Ch] [bp-4Ch]@1
signed int v37; // [sp+90h] [bp-48h]@1
signed int v38; // [sp+94h] [bp-44h]@1
char v39; // [sp+98h] [bp-40h]@1
char v40; // [sp+99h] [bp-3Fh]@1
char v41; // [sp+9Ah] [bp-3Eh]@1
char v42; // [sp+9Bh] [bp-3Dh]@1
unsigned int iv; // [sp+9Ch] [bp-3Ch]@1
unsigned int v44; // [sp+A0h] [bp-38h]@1
unsigned int v45; // [sp+A4h] [bp-34h]@1
unsigned int v46; // [sp+A8h] [bp-30h]@1
int v47; // [sp+ACh] [bp-2Ch]@1
output = a1;
str_in_ = str_in;
v47 = _stack_chk_guard;
iv = 0x3020100u;
v44 = 0x7060504u;
v45 = 0xB0A0908u;
v46 = 0xF0E0D0Cu;
algo_name = 'njir';
v37 = 'lead';
v38 = '291-';
v39 = aRijndael192[12];
v40 = 0;
v41 = 0;
v42 = 0;
ECB_mode = 'bce';
if ( *(_DWORD *)(*(_DWORD *)str_in - 12) )
{
my_str_alloc2((int)&v21, "%2b", (int)&v34);
my_str_alloc2((int)&v20, "+", (int)&v33);
my_func((int)&v22, str_in_, (int)&v21, (int)&v20);
v4 = (void *)(v20 - 12);
if ( (_UNKNOWN *)(v20 - 12) != &unk_D4A8C && sub_91FB0(v20 - 4, -1) <= 0 )
operator delete(v4);
v5 = (void *)(v21 - 12);
if ( &unk_D4A8C != (_UNKNOWN *)(v21 - 12) && sub_91FB0(v21 - 4, -1) <= 0 )
operator delete(v5);
if ( *(_DWORD *)(v22 - 12) > 9u )
{
cipher_ctx = my_encryptor((const char *)&algo_name, 0, (const char *)&ECB_mode, 0);
if ( cipher_ctx )
{
my_substr(&src, &v22, 2, 8);
if ( *((_DWORD *)src - 3) == 8 )
{
key = malloc(8u);
memcpy(key, src, 8u);
if ( my_setkey2(cipher_ctx, (int)key, 8, (int)&iv) < 0 )
{
free(key);
my_str_alloc2(output, &my_data, (int)&v30);
}
else
{
v9 = v22;
if ( !*(_DWORD *)(v22 - 12) )
sub_508B4("basic_string::at");
if ( *(_DWORD *)(v22 - 4) >= 0 )
{
my_get_rawptr((int)&v22);
v9 = v22;
}
v13 = *(_BYTE *)v9;
my_substr(&v18, &v22, 10, -1);
if ( *(_DWORD *)(v18 - 12) )
{
my_str_cpy(&v16, &v18);
my_decode_b64(&v17, &v16);
my_delete(&v16);
n = *((_DWORD *)v17 - 3);
if ( n )
{
ptr = malloc(n + 1);
memset(ptr, 0, n + 1);
memcpy(ptr, v17, n);
if ( my_decrypt_wrap(cipher_ctx, (int)ptr, n) )
{
free(key);
free(ptr);
my_str_alloc2(output, &my_data, (int)&v27);
}
else
{
my_strwrapper((int)&v15, (int)ptr, n);
if ( *((_DWORD *)v15 - 3) )
{
memset(ptr, 0, n);
memcpy(ptr, v15, *((_DWORD *)v15 - 3));
my_xor_encrypt((int)ptr, *((_DWORD *)v15 - 3), v13);
sub_396C0(cipher_ctx);
sub_39D5C(cipher_ctx);
v14 = std::string::_S_construct<unsigned_char__>((int)ptr, (int)((char *)ptr + n));
free(key);
free(ptr);
my_str_alloc2(output, (const char *)v14, (int)&v25);
my_delete(&v14);
}
else
{
free(key);
free(ptr);
my_str_alloc2(output, &my_data, (int)&v26);
}
my_delete(&v15);
}
}
else
{
free(key);
my_str_alloc2(output, &my_data, (int)&v28);
}
my_delete(&v17);
}
else
{
free(key);
my_str_alloc2(output, &my_data, (int)&v29);
}
my_delete(&v18);
}
}
else
{
my_str_alloc2(output, &my_data, (int)&v31);
}
my_delete(&src);
}
else
{
my_str_alloc2(output, &my_data, (int)&v24);
}
}
else
{
my_str_alloc2(output, &my_data, (int)&v32);
}
v6 = (void *)(v22 - 12);
if ( &unk_D4A8C != (_UNKNOWN *)(v22 - 12) && sub_91FB0(v22 - 4, -1) <= 0 )
operator delete(v6);
}
else
{
my_str_alloc2(a1, &my_data, (int)&v35);
}
result = output;
if ( v47 != _stack_chk_guard )
_stack_chk_fail(output);
return result;
}
else
{
v22 = *(_DWORD *)(cipher_ctx_ + 136); // data
v23 = *(_DWORD *)(cipher_ctx_ + 144); // key
iv_size = 0;
if ( iv_ )
iv_size = my_ivlen(cipher_ctx_);
v25 = my_setkey(cipher_ctx_, v22, v23, keylen, iv_, iv_size);
result = 0;
memcpy(&v14, (const void *)(buffer_ + 16), 0x34u);
*(_DWORD *)(buffer_ + 156) = sub_39EFC(
*(_DWORD *)buffer_,
*(_DWORD *)(buffer_ + 4),
*(_DWORD *)(buffer_ + 8),
*(_DWORD *)(buffer_ + 12),
v14,
v15,
v16,
v17,
v18,
v19,
v20,
v21,
v22,
v23,
v24,
v25,
v26,
(int)"_mcrypt_encrypt");
*(_DWORD *)(buffer_ + 152) = sub_39EFC(
*(_DWORD *)(buffer_ + 68),
*(_DWORD *)(buffer_ + 72),
*(_DWORD *)(buffer_ + 76),
*(_DWORD *)(buffer_ + 80),
v14,
v15,
v16,
v17,
v18,
v19,
v20,
v21,
v22,
v23,
v24,
v25,
v26,
(int)"_mdecrypt");
memcpy(&v14, (const void *)(buffer_ + 84), 0x34u);
*(_DWORD *)(buffer_ + 148) = sub_39EFC(
*(_DWORD *)(buffer_ + 68),
*(_DWORD *)(buffer_ + 72),
*(_DWORD *)(buffer_ + 76),
*(_DWORD *)(buffer_ + 80),
v14,
v15,
v16,
v17,
v18,
v19,
v20,
v21,
v22,
v23,
v24,
v25,
v26,
(int)"_mcrypt");
v27 = (int)"_mdecrypt";
memcpy(&v14, (const void *)(buffer_ + 84), 0x34u);
*(_DWORD *)(buffer_ + 152) = sub_39EFC(
*(_DWORD *)(buffer_ + 68),
*(_DWORD *)(buffer_ + 72),
*(_DWORD *)(buffer_ + 76),
*(_DWORD *)(buffer_ + 80),
v14,
v15,
v16,
v17,
v18,
v19,
v20,
v21,
v22,
v23,
v24,
v25,
v26,
(int)"_mdecrypt");
v27 = (int)"_mcrypt_get_block_size";
memcpy(&v14, (const void *)(buffer_ + 16), 0x34u);
v11 = sub_39EFC(
*(_DWORD *)buffer_,
*(_DWORD *)(buffer_ + 4),
*(_DWORD *)(buffer_ + 8),
*(_DWORD *)(buffer_ + 12),
v14,
v15,
v16,
v17,
v18,
v19,
v20,
v21,
v22,
v23,
v24,
v25,
v26,
(int)"_mcrypt_get_block_size");
*(_DWORD *)(buffer_ + 164) = v11;
if ( *(_DWORD *)(buffer_ + 156)
&& *(_DWORD *)(buffer_ + 160)
&& *(_DWORD *)(buffer_ + 148)
&& *(_DWORD *)(buffer_ + 152)
&& v11 )
{
v12 = sub_39F70(buffer_);
if ( v12 != sub_3A124(buffer_) )
{
sub_39D5C(buffer_);
buffer_ = 0;
}
}
else
{
free(buffer__);
buffer_ = 0;
}
}
v20 = my_mode_getsize(cipher_ctx_);
if ( (signed int)v20 <= 0 )
{
v21 = *(_DWORD *)(cipher_ctx_ + 140);
}
else
{
v21 = (int)my_calloc(1u, v20);
*(_DWORD *)(cipher_ctx_ + 140) = v21;
if ( !v21 )
{
free(*(void **)(cipher_ctx_ + 144));
free(*(void **)(cipher_ctx_ + 136));
return -4;
}
}
YOPIZYVILYD0hJrdZLpy9qs195VRRk3xDXOi8WFj9u
WEJWLUZWBGpRVgVxS4OV8/LmohNQdhVoSNduuROh85A5YxBUpK5eWEaVCIIlnkuK
WEJWLUZWBGpRVgVxS4OV8/LmohNQdhVoSNduuROh85A5YxBUpK5eWEaVCIIlnkuKyb6WonkSO6
2~10 바이트 : RIJNDAEL 키.
1 바이트 : XOR 키.
base64 데이터 : 11바이트째부터
'Programming' 카테고리의 다른 글
FreeBSD system call table (0) | 2013.07.10 |
---|---|
Kernel module compile example (0) | 2013.07.08 |
FreeBSD pkg_add package install (0) | 2013.07.01 |
python malware scanner (0) | 2013.06.29 |
Alpine Linux on QEMU (0) | 2013.06.28 |