Home page logo

fulldisclosure logo Full Disclosure mailing list archives

Re: Patriotic botnet with Orange's HADOPI software
From: no no <procrastinateur.fr () gmail com>
Date: Tue, 15 Jun 2010 20:20:45 +0200

Malware like

The service (cdtsvc) doesn't allow configuration change :
if the user changes the service config, it is instantly reset to "default"
values : restart when killed, user cannot stop it manually

This behaviour is bypassable : create the following registry key and the
service will no longer reset the configuration each time it is changed :
value : 128

This way, the service can be killed and restarted "on demand"

User Configuration
During the install, the user has to set a secret question with the
associated answer in case he forgets its password
Even if the password is stored hashed in the registry, the secret question,
the answer as well as other parameters are stored encrypted

$ cat decrypt_configuration.py

from ctypes import *
from ctypes.wintypes import DWORD
from _winreg import *
import struct
import sys

LocalFree = windll.kernel32.LocalFree
memcpy = cdll.msvcrt.memcpy
CryptProtectData = windll.crypt32.CryptProtectData
CryptUnprotectData = windll.crypt32.CryptUnprotectData

aReg = ConnectRegistry(None,HKEY_LOCAL_MACHINE)
aKey = OpenKey(aReg, r"SYSTEM\CurrentControlSet\Services\cdtsvc\Parameters")

config = QueryValueEx(aKey,"Config")[0]

class DATA_BLOB(Structure):
    _fields_ = [("cbData", DWORD), ("pbData", POINTER(c_char))]

def getData(blobOut):
    cbData = int(blobOut.cbData)
    pbData = blobOut.pbData
    buffer = c_buffer(cbData)
    memcpy(buffer, pbData, cbData)
    return buffer.raw

def Win32CryptUnprotectData(cipherText):
    bufferIn = c_buffer(cipherText, len(cipherText))
    blobIn = DATA_BLOB(len(cipherText), bufferIn)
    blobOut = DATA_BLOB()
    if CryptUnprotectData(byref(blobIn), None, None, None, None,
                              CRYPTPROTECT_UI_FORBIDDEN, byref(blobOut)):
        return getData(blobOut)
        return ""

dec = Win32CryptUnprotectData(config)
print "="*60
print "Configuration in
print "="*60+"\n\n"
# the encrypted message begins with the number of blocks (key/value) on 4

nb_block = struct.unpack("<l",dec[:4])[0]
dec = dec[4:]
for i in range(nb_block):
    # then, each block : 2 bytes for the block size, 1 byte key length (each
character of the key is 2 bytes long because widechar are used, and we also
have a final \0
    # so for key "MyKey" , lg_key = 0xC (12) )
    # then the key (key name), the its value (we know the value length
lg_value = lg_block - lg_key - 3 (2 bytes for lg_block et 1 byte for lg_key)
    lg_block = struct.unpack("<h",dec[:2])[0]
    lg_key = ord(dec[2]) # widechar so 2 bytes per char , and a final \0 so
add 2 more bytes
    current = dec[:lg_block]
    key = current[3:lg_key*2].replace('\x00','')
    value = current[lg_key*2:].replace('\x00','')
    print "%s : %s"%(key,value)
    dec = dec[lg_block:]

Unluckily, the config can be decrypted only by the SYSTEM account, so this
script must be run as SYSTEM :

either run this script as a service
or, on Windows XP, use the "at" trick in a cmd :

at XX:XX /interactive cmd.exe

XX:XX being current time + 1 min

in the shell that spawns, run this script

What I haven't figured out yet is : why this RSA public key ? from your
analysis, no signature or signature check is performed and I haven't figured
it either
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

  By Date           By Thread  

Current thread:
[ Nmap | Sec Tools | Mailing Lists | Site News | About/Contact | Advertising | Privacy ]