📄 drms.c
字号:
static int GetUserKey( void *_p_drms, uint32_t *p_user_key )
{
static char const p_secret[] = "mUfnpognadfgf873";
struct drms_s *p_drms = (struct drms_s *)_p_drms;
struct aes_s aes;
struct shuffle_s shuffle;
uint32_t i, y;
uint32_t *p_sci_data;
uint32_t i_user, i_key;
uint32_t p_sys_key[ 4 ];
uint32_t i_sci_size, i_blocks, i_remaining;
uint32_t *p_sci0, *p_sci1, *p_buffer;
uint32_t p_sci_key[ 4 ];
char *psz_ipod;
int i_ret = -1;
if( !ReadUserKey( p_drms, p_user_key ) )
{
REVERSE( p_user_key, 4 );
return 0;
}
psz_ipod = getenv( "IPOD" );
if( GetSystemKey( p_sys_key, psz_ipod ? 1 : 0 ) )
{
return -1;
}
if( GetSCIData( psz_ipod, &p_sci_data, &i_sci_size ) )
{
return -1;
}
/* Phase 1: unscramble the SCI data using the system key and shuffle
* it using DoShuffle(). */
/* Skip the first 4 bytes (some sort of header). Decrypt the rest. */
i_blocks = (i_sci_size - 4) / 16;
i_remaining = (i_sci_size - 4) - (i_blocks * 16);
p_buffer = p_sci_data + 1;
/* Decrypt and shuffle our data at the same time */
InitAES( &aes, p_sys_key );
REVERSE( p_sys_key, 4 );
InitShuffle( &shuffle, p_sys_key );
memcpy( p_sci_key, p_secret, 16 );
REVERSE( p_sci_key, 4 );
while( i_blocks-- )
{
uint32_t p_tmp[ 4 ];
REVERSE( p_buffer, 4 );
DecryptAES( &aes, p_tmp, p_buffer );
BlockXOR( p_tmp, p_sci_key, p_tmp );
/* Use the previous scrambled data as the key for next block */
memcpy( p_sci_key, p_buffer, 16 );
/* Shuffle the decrypted data using a custom routine */
DoShuffle( &shuffle, p_tmp, 4 );
/* Copy this block back to p_buffer */
memcpy( p_buffer, p_tmp, 16 );
p_buffer += 4;
}
if( i_remaining >= 4 )
{
i_remaining /= 4;
REVERSE( p_buffer, i_remaining );
DoShuffle( &shuffle, p_buffer, i_remaining );
}
/* Phase 2: look for the user key in the generated data. I must admit I
* do not understand what is going on here, because it almost
* looks like we are browsing data that makes sense, even though
* the DoShuffle() part made it completely meaningless. */
y = 0;
REVERSE( p_sci_data + 5, 1 );
i = U32_AT( p_sci_data + 5 );
i_sci_size -= 22 * sizeof(uint32_t);
p_sci1 = p_sci_data + 22;
p_sci0 = NULL;
while( i_sci_size >= 20 && i > 0 )
{
if( p_sci0 == NULL )
{
i_sci_size -= 18 * sizeof(uint32_t);
if( i_sci_size < 20 )
{
break;
}
p_sci0 = p_sci1;
REVERSE( p_sci1 + 17, 1 );
y = U32_AT( p_sci1 + 17 );
p_sci1 += 18;
}
if( !y )
{
i--;
p_sci0 = NULL;
continue;
}
i_user = U32_AT( p_sci0 );
i_key = U32_AT( p_sci1 );
REVERSE( &i_user, 1 );
REVERSE( &i_key, 1 );
if( i_user == p_drms->i_user && ( ( i_key == p_drms->i_key ) ||
( !p_drms->i_key && ( p_sci1 == (p_sci0 + 18) ) ) ) )
{
memcpy( p_user_key, p_sci1 + 1, 16 );
REVERSE( p_sci1 + 1, 4 );
WriteUserKey( p_drms, p_sci1 + 1 );
i_ret = 0;
break;
}
y--;
p_sci1 += 5;
i_sci_size -= 5 * sizeof(uint32_t);
}
free( p_sci_data );
return i_ret;
}
/*****************************************************************************
* GetSCIData: get SCI data from "SC Info.sidb"
*****************************************************************************
* Read SCI data from "\Apple Computer\iTunes\SC Info\SC Info.sidb"
*****************************************************************************/
static int GetSCIData( char *psz_ipod, uint32_t **pp_sci,
uint32_t *pi_sci_size )
{
FILE *file;
char *psz_path = NULL;
char p_tmp[ PATH_MAX ];
int i_ret = -1;
if( psz_ipod == NULL )
{
#ifdef _WIN32
char *p_filename = "\\Apple Computer\\iTunes\\SC Info\\SC Info.sidb";
typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
LPSTR );
HINSTANCE shfolder_dll = NULL;
SHGETFOLDERPATH dSHGetFolderPath = NULL;
if( ( shfolder_dll = LoadLibrary( _T("SHFolder.dll") ) ) != NULL )
{
dSHGetFolderPath =
(SHGETFOLDERPATH)GetProcAddress( shfolder_dll,
_T("SHGetFolderPathA") );
}
if( dSHGetFolderPath != NULL &&
SUCCEEDED( dSHGetFolderPath( NULL, /*CSIDL_COMMON_APPDATA*/ 0x0023,
NULL, 0, p_tmp ) ) )
{
strncat( p_tmp, p_filename, min( strlen( p_filename ),
(sizeof(p_tmp)/sizeof(p_tmp[0]) - 1) -
strlen( p_tmp ) ) );
psz_path = p_tmp;
}
if( shfolder_dll != NULL )
{
FreeLibrary( shfolder_dll );
}
#endif
}
else
{
#define ISCINFO "iSCInfo"
if( strstr( psz_ipod, ISCINFO ) == NULL )
{
sprintf( p_tmp, /*sizeof(p_tmp)/sizeof(p_tmp[0]) - 1,*/
"%s/iPod_Control/iTunes/" ISCINFO, psz_ipod );
psz_path = p_tmp;
}
else
{
psz_path = psz_ipod;
}
}
if( psz_path == NULL )
{
return -1;
}
file = fopen( psz_path, "r" );
if( file != NULL )
{
struct stat st;
if( !fstat( fileno( file ), &st ) )
{
*pp_sci = malloc( st.st_size );
if( *pp_sci != NULL )
{
if( fread( *pp_sci, 1, st.st_size,
file ) == (size_t)st.st_size )
{
*pi_sci_size = st.st_size;
i_ret = 0;
}
else
{
free( (void *)*pp_sci );
*pp_sci = NULL;
}
}
}
fclose( file );
}
return i_ret;
}
/*****************************************************************************
* HashSystemInfo: hash system information
*****************************************************************************
* This function computes the MD5 hash of the C: hard drive serial number,
* BIOS version, CPU type and Windows version.
*****************************************************************************/
static int HashSystemInfo( uint32_t *p_system_hash )
{
struct md5_s md5;
int i_ret = 0;
#ifdef _WIN32
HKEY i_key;
unsigned int i;
DWORD i_size;
DWORD i_serial;
LPBYTE p_reg_buf;
static LPCTSTR p_reg_keys[ 3 ][ 2 ] =
{
{
_T("HARDWARE\\DESCRIPTION\\System"),
_T("SystemBiosVersion")
},
{
_T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
_T("ProcessorNameString")
},
{
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion"),
_T("ProductId")
}
};
InitMD5( &md5 );
AddMD5( &md5, "cache-control", 13 );
AddMD5( &md5, "Ethernet", 8 );
GetVolumeInformation( _T("C:\\"), NULL, 0, &i_serial,
NULL, NULL, NULL, 0 );
AddMD5( &md5, (uint8_t *)&i_serial, 4 );
for( i = 0; i < sizeof(p_reg_keys) / sizeof(p_reg_keys[ 0 ]); i++ )
{
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, p_reg_keys[ i ][ 0 ],
0, KEY_READ, &i_key ) != ERROR_SUCCESS )
{
continue;
}
if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ],
NULL, NULL, NULL, &i_size ) != ERROR_SUCCESS )
{
RegCloseKey( i_key );
continue;
}
p_reg_buf = malloc( i_size );
if( p_reg_buf != NULL )
{
if( RegQueryValueEx( i_key, p_reg_keys[ i ][ 1 ],
NULL, NULL, p_reg_buf,
&i_size ) == ERROR_SUCCESS )
{
AddMD5( &md5, (uint8_t *)p_reg_buf, i_size );
}
free( p_reg_buf );
}
RegCloseKey( i_key );
}
#else
InitMD5( &md5 );
i_ret = -1;
#endif
EndMD5( &md5 );
memcpy( p_system_hash, md5.p_digest, 16 );
return i_ret;
}
/*****************************************************************************
* GetiPodID: Get iPod ID
*****************************************************************************
* This function gets the iPod ID.
*****************************************************************************/
static int GetiPodID( int64_t *p_ipod_id )
{
int i_ret = -1;
#define PROD_NAME "iPod"
#define VENDOR_NAME "Apple Computer, Inc."
char *psz_ipod_id = getenv( "IPODID" );
if( psz_ipod_id != NULL )
{
#ifndef _WIN32
*p_ipod_id = strtoll( psz_ipod_id, NULL, 16 );
#else
*p_ipod_id = strtol( psz_ipod_id, NULL, 16 );
#endif
return 0;
}
#ifdef HAVE_IOKIT_IOKITLIB_H
CFTypeRef value;
mach_port_t port;
io_object_t device;
io_iterator_t iterator;
CFMutableDictionaryRef matching_dic;
if( IOMasterPort( MACH_PORT_NULL, &port ) == KERN_SUCCESS )
{
if( ( matching_dic = IOServiceMatching( "IOFireWireUnit" ) ) != NULL )
{
CFDictionarySetValue( matching_dic,
CFSTR("FireWire Vendor Name"),
CFSTR(VENDOR_NAME) );
CFDictionarySetValue( matching_dic,
CFSTR("FireWire Product Name"),
CFSTR(PROD_NAME) );
if( IOServiceGetMatchingServices( port, matching_dic,
&iterator ) == KERN_SUCCESS )
{
while( ( device = IOIteratorNext( iterator ) ) != NULL )
{
value = IORegistryEntryCreateCFProperty( device,
CFSTR("GUID"), kCFAllocatorDefault, kNilOptions );
if( value != NULL )
{
if( CFGetTypeID( value ) == CFNumberGetTypeID() )
{
int64_t i_ipod_id;
CFNumberGetValue( (CFNumberRef)value,
kCFNumberLongLongType,
&i_ipod_id );
*p_ipod_id = i_ipod_id;
i_ret = 0;
}
CFRelease( value );
}
IOObjectRelease( device );
if( !i_ret ) break;
}
IOObjectRelease( iterator );
}
}
mach_port_deallocate( mach_task_self(), port );
}
#elif HAVE_SYSFS_LIBSYSFS_H
struct sysfs_bus *bus = NULL;
struct dlist *devlist = NULL;
struct dlist *attributes = NULL;
struct sysfs_device *curdev = NULL;
struct sysfs_attribute *curattr = NULL;
bus = sysfs_open_bus( "ieee1394" );
if( bus != NULL )
{
devlist = sysfs_get_bus_devices( bus );
if( devlist != NULL )
{
dlist_for_each_data( devlist, curdev, struct sysfs_device )
{
attributes = sysfs_get_device_attributes( curdev );
if( attributes != NULL )
{
dlist_for_each_data( attributes, curattr,
struct sysfs_attribute )
{
if( ( strcmp( curattr->name, "model_name" ) == 0 ) &&
( strncmp( curattr->value, PROD_NAME,
sizeof(PROD_NAME) ) == 0 ) )
{
*p_ipod_id = strtoll( curdev->name, NULL, 16 );
i_ret = 0;
break;
}
}
}
if( !i_ret ) break;
}
}
sysfs_close_bus( bus );
}
#endif
return i_ret;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -