📄 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 + -