/* This file was generated by the Hex-Rays decompiler. Copyright (c) 2007-2020 Hex-Rays Detected compiler: GNU C++ */ //#include "defs.h" #include #include #include #include #include #include #include #include #include #include #include typedef struct __attribute__((aligned(4))) { uint32_t magic; uint32_t rsaLen; uint32_t crc32sum; uint16_t romType; int16_t model; uint32_t fileOffs[8]; } MiRomHdr; typedef struct { uint16_t magic; uint16_t rsvd0; uint32_t flashaddr; uint32_t filesize; uint16_t mtdid; uint16_t unk5; char name[32]; } MiRomFile; //------------------------------------------------------------------------- // Function declarations void error_exit(); size_t util_get_file_len(FILE *a1); int util_check_model_idx(int16_t model_idx); int main(int argc, const char **argv, const char **envp); int for_each_file(FILE *f, int (*callback)(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata), void *userData); int load_image(FILE *f, int disableVerify); int command_verify_image(const char *filename); int extract_normal_rom_callback(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata); int command_extract_file(const char *filename, const char *sshFile, int disableVerify, const char *fname, int outputToFile); int flash_mtd_callback(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata); int command_mtd_flash(const char *filename, int needVerify); int dump_file_desc(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata); int command_list_files(const char *image, const char *a2); int get_version_callback(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata); int command_get_image_version(const char *a1); int command_get_ssh_key(); unsigned int crc32_update(uint8_t *buf, int64_t size, unsigned int state); uint32_t calc_crc32(FILE *f, int start, unsigned int size); int64_t init_pkey(EVP_MD_CTX *ctx, RSA **pem, EVP_PKEY **ppkey, int isSsh); // idb int j_verify_rsa(FILE *f, unsigned int start, unsigned int size, const unsigned char *sigbuf, unsigned int siglen, unsigned int isSsh); int verify_rsa(FILE *f, int start, unsigned int size, const unsigned char *sigbuf, unsigned int siglen, unsigned int isSsh); int64_t write_buf(int fd, void *buf, unsigned int size); int open_and_erase_mtd(unsigned int mtdId); int64_t calcMd5(unsigned char *a1, const char *a2); int64_t transpostGuid(uint8_t *a1, char *outbuf); int64_t get_ssh_key(); int extract_ssh_rom_callback(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata); //------------------------------------------------------------------------- // Data declarations uint32_t crc32_table[256] = { 0, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; char *model_nr[30] = { "NULL", "NULL", "NULL", "R1CM", "R2D", "R1CL", "R2CM", "R3", "R3D", "R3L", "R3P", "P01", "R3A", "R3G", "R4", "R4C", "D01", "R4A", "R4CM", "R4AC", "R3GV2", "R2600", "R2100", "RM2100", "R3600", "R1350", "R2200", "R2350", "IR1200G", "R1800" }; // weak int max_model_nr = 30; // weak //----- (0000000000401730) ---------------------------------------------------- void error_exit() { fwrite("Ouch!\n", 1u, 6u, stderr); exit(1); } //----- (00000000004017A4) ---------------------------------------------------- size_t util_get_file_len(FILE *a1) { size_t v3; // [xsp+28h] [xbp+28h] int v4; // [xsp+2Ch] [xbp+2Ch] v4 = ftell(a1); fseek(a1, 0LL, 2); v3 = ftell(a1); fseek(a1, v4, 0); return v3; } //----- (00000000004017F8) ---------------------------------------------------- int util_check_model_idx(int16_t model_idx) { int result; // w0 char v3[8]; // [xsp+20h] [xbp+20h] BYREF FILE *stream; // [xsp+28h] [xbp+28h] memset(v3, 0, 8); stream = popen("cat /proc/xiaoqiang/model", "r"); if ( stream ) { if ( fgets(v3, 8, stream) ) { pclose(stream); if ( model_idx < max_model_nr ) { result = strcmp(v3, model_nr[model_idx]); } else { fprintf( stderr, "Illegal model: model_idx=%d,max_model_nr=%d \n", (unsigned int)model_idx, (unsigned int)max_model_nr); result = -1; } } else { fwrite("Failed to get model \n", 1u, 0x15u, stderr); result = -1; } } else { fwrite("Failed to run command\n", 1u, 0x16u, stderr); result = -1; } return result; } //----- (0000000000401918) ---------------------------------------------------- int main(int argc, const char **argv, const char **envp) { int v6; // [xsp+20h] [xbp+20h] int ret; // [xsp+24h] [xbp+24h] const char *filename; // [xsp+28h] [xbp+28h] const char *a2; // [xsp+30h] [xbp+30h] const char *file; // [xsp+38h] [xbp+38h] int toStdout; // [xsp+44h] [xbp+44h] int disableVerify; // [xsp+48h] [xbp+48h] int mode; // [xsp+4Ch] [xbp+4Ch] mode = -1; disableVerify = 0; toStdout = 0; file = 0LL; a2 = 0LL; filename = 0LL; OPENSSL_add_all_algorithms_noconf(); while ( 1 ) { v6 = getopt(argc, (char *const *)argv, "-v:x:w:c:V:Io:s:m:t:p:f:S:rn"); if ( v6 == -1 ) break; switch ( v6 ) { case 'I': mode = 6; continue; case 'S': a2 = optarg; continue; case 'V': mode = 5; filename = optarg; continue; case 'c': mode = 4; filename = optarg; continue; case 'f': if ( mode != 2 && mode != 4 ) continue; if ( file ) { fwrite("Multiple files specified\n", 1u, 0x19u, stderr); return -22; } file = optarg; break; case 'n': toStdout = 1; continue; case 'r': disableVerify = 1; continue; case 'v': mode = 1; filename = optarg; continue; case 'w': mode = 3; filename = optarg; continue; case 'x': mode = 2; filename = optarg; continue; default: error_exit(); } } switch ( mode ) { case 1: ret = command_verify_image(filename); break; case 2: ret = command_extract_file(filename, a2, disableVerify, file, toStdout); break; case 3: ret = command_mtd_flash(filename, disableVerify); break; case 4: ret = command_list_files(filename, file); break; case 5: ret = command_get_image_version(filename); break; case 6: ret = command_get_ssh_key(); break; default: error_exit(); } return ret; } //----- (0000000000401BAC) ---------------------------------------------------- int for_each_file(FILE *f, int (*callback)(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata), void *userData) { MiRomFile filehdr; // [xsp+30h] [xbp+30h] BYREF MiRomHdr buf; // [xsp+60h] [xbp+60h] BYREF size_t readret; // [xsp+90h] [xbp+90h] unsigned int off; // [xsp+94h] [xbp+94h] int ret; // [xsp+98h] [xbp+98h] int fileid; // [xsp+9Ch] [xbp+9Ch] ret = 0; off = 0; if ( !callback ) return -1; rewind(f); readret = fread(&buf, 1u, 0x30u, f); if ( ferror(f) ) return 0xFFFFFFFB; for ( fileid = 0; fileid <= 7; ++fileid ) { off = buf.fileOffs[fileid]; if ( !off ) break; ret = fseek(f, off, 0); if ( ret ) break; readret = fread(&filehdr, 1u, 0x30u, f); if ( readret != 48 ) return -5; ret = callback(&buf, (unsigned char)fileid, &filehdr, f, userData); if ( ret ) return ret; } return ret; } //----- (0000000000401D08) ---------------------------------------------------- int load_image(FILE *f, int disableVerify) { unsigned char sigbuf[4096]; // [xsp+20h] [xbp+20h] BYREF size_t sigsize[4]; // [xsp+1020h] [xbp+1020h] BYREF MiRomHdr hdr; // [xsp+1030h] [xbp+1030h] BYREF uint32_t crcret; // [xsp+1064h] [xbp+1064h] short model_idx; // [xsp+106Ah] [xbp+106Ah] size_t ret; // [xsp+106Ch] [xbp+106Ch] size_t len; // [xsp+1070h] [xbp+1070h] uint16_t v12; // [xsp+1076h] [xbp+1076h] unsigned int isSsh; // [xsp+1078h] [xbp+1078h] int verify_ret; // [xsp+107Ch] [xbp+107Ch] memset(sigbuf, 0, sizeof(sigbuf)); v12 = -1; verify_ret = 0; len = 0; isSsh = 0; rewind(f); ret = fread(&hdr, 1u, 0x30u, f); if ( ret != 0x30 ) return 0xFFFFFFFB; if ( hdr.magic != '1RDH' ) { fwrite("Invalid image block\n", 1u, 0x14u, stderr); return -22; } model_idx = hdr.model; if ( util_check_model_idx(hdr.model) ) { fwrite("Model mismatch\n", 1u, 0xFu, stderr); return -22; } len = util_get_file_len(f); rewind(f); crcret = calc_crc32(f, 12, len - 12); if ( hdr.crc32sum != crcret ) { fwrite("Image checksum is invalid\n", 1u, 0x1Au, stderr); return -22; } v12 = hdr.romType; if ( hdr.romType == 12 ) isSsh = 1; if ( disableVerify ) { verify_ret = 0; } else { fseek(f, hdr.rsaLen, SEEK_SET); ret = fread(sigsize, 1u, 0x10u, f); if ( ret != 16 ) return -5; ret = fread(sigbuf, 1u, sigsize[0], f); if ( sigsize[0] != ret ) return -5; rewind(f); verify_ret = j_verify_rsa(f, 12u, hdr.rsaLen - 12, sigbuf, sigsize[0], isSsh); } if ( !verify_ret ) return 0; fwrite("Image verify failed, not formal image\n", 1u, 0x26u, stderr); return -22; } //----- (0000000000401FBC) ---------------------------------------------------- int command_verify_image(const char *filename) { FILE *stream; // [xsp+20h] [xbp+20h] int v4; // [xsp+2Ch] [xbp+2Ch] stream = fopen(filename, "r"); if ( stream ) { v4 = load_image(stream, 0); fclose(stream); } else { fprintf(stderr, "can not open \"%s\" for reading\n", filename); v4 = -2; } return v4; } //----- (0000000000402048) ---------------------------------------------------- int extract_normal_rom_callback(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata) { int64_t v5; // x0 size_t v9; // [xsp+4Ch] [xbp+4Ch] void *ptr; // [xsp+50h] [xbp+50h] char *fname; // [xsp+58h] [xbp+58h] int v13; // [xsp+6Ch] [xbp+6Ch] size_t chunksize; // [xsp+70h] [xbp+70h] uint32_t filesize; // [xsp+74h] [xbp+74h] FILE *s; // [xsp+78h] [xbp+78h] v13 = 0; fname = *(char **)userdata; if ( fildhdr->filesize <= 7 || fildhdr->magic != 0xBABE ) return 0; if ( fname && strcmp(fildhdr->name, fname) ) return 0; if ( *((uint32_t *)userdata + 2) ) { s = (FILE *)stdout; } else { s = fopen(fildhdr->name, "w"); if ( !s ) { fprintf(stderr, "can not open \"%s\" for writing\n", fildhdr->name); return -5; } } ptr = malloc(0x10000u); if ( ptr ) { filesize = fildhdr->filesize; while ( filesize ) { v9 = fread(ptr, 1u, 0x10000u, f); if ( filesize < v9 ) { chunksize = filesize; v5 = fwrite(ptr, filesize, 1u, s); } else { chunksize = v9; v5 = fwrite(ptr, v9, 1u, s); } if ( !v5 || fflush(s) ) { fwrite("fwrite failed\n", 1u, 0xEu, stderr); v13 = -5; goto LABEL_26; } filesize -= chunksize; if ( feof(f) && filesize ) { fwrite("File too short while required write length too long\n", 1u, 0x34u, stderr); v13 = -5; goto LABEL_26; } } if ( fname ) v13 = 1; LABEL_26: free(ptr); } else { fwrite("malloc failed\n", 1u, 0xEu, stderr); v13 = -12; } if ( !*((uint32_t *)userdata + 2) ) fclose(s); return v13; } // 414DC8: using guessed type int64_t stdout; //----- (00000000004022F8) ---------------------------------------------------- int command_extract_file(const char *filename, const char *sshFile, int disableVerify, const char *fname, int outputToFile) { void *v10[2]; // [xsp+38h] [xbp+38h] BYREF MiRomHdr hdr; // [xsp+48h] [xbp+48h] BYREF size_t v12; // [xsp+78h] [xbp+78h] uint16_t v13; // [xsp+7Eh] [xbp+7Eh] FILE *stream; // [xsp+80h] [xbp+80h] int ret; // [xsp+8Ch] [xbp+8Ch] ret = 0; v13 = 0; v10[1] = (void *)outputToFile; v10[0] = fname; stream = fopen(filename, "r"); if ( stream ) { ret = load_image(stream, disableVerify); if ( !ret ) { rewind(stream); v12 = fread(&hdr, 1u, 0x30u, stream); if ( v12 == 48 ) { v13 = hdr.romType; if ( hdr.romType == 12 ) ret = for_each_file(stream, extract_ssh_rom_callback, (void *)sshFile); else ret = for_each_file(stream, extract_normal_rom_callback, v10); if ( fname ) { if ( ret <= 0 ) { if ( !ret ) ret = -2; } else { ret = 0; } } } else { ret = -5; } } fclose(stream); } else { fprintf(stderr, "can not open \"%s\" for reading\n", filename); ret = -2; } return ret; } //----- (0000000000402484) ---------------------------------------------------- int flash_mtd_callback(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata) { unsigned int v8; // [xsp+44h] [xbp+44h] void *buf; // [xsp+48h] [xbp+48h] int fd; // [xsp+50h] [xbp+50h] int v11; // [xsp+54h] [xbp+54h] unsigned int size; // [xsp+58h] [xbp+58h] unsigned int filesize; // [xsp+5Ch] [xbp+5Ch] v11 = 0; if ( fildhdr->filesize <= 7 || fildhdr->magic != 0xBABE ) return v11; if ( fildhdr->mtdid == 0xFFFF ) { printf("Skip offset[%hhu]\n", (unsigned char)fileid); } else { fd = open_and_erase_mtd(fildhdr->mtdid); buf = malloc(0x10000u); if ( buf ) { filesize = fildhdr->filesize; while ( filesize ) { v8 = fread(buf, 1u, 0x10000u, f); if ( filesize < v8 ) { size = filesize; write_buf(fd, buf, filesize); } else { size = v8; write_buf(fd, buf, v8); } filesize -= size; if ( feof(f) && filesize ) { fwrite("File too short while required write length too long\n", 1u, 0x34u, stderr); free(buf); v11 = -5; break; } } } else { fwrite("malloc failed\n", 1u, 0xEu, stderr); v11 = -12; } close(fd); } return v11; } //----- (0000000000402628) ---------------------------------------------------- int command_mtd_flash(const char *filename, int needVerify) { FILE *stream; // [xsp+20h] [xbp+20h] int v6; // [xsp+2Ch] [xbp+2Ch] stream = fopen(filename, "r"); if ( stream ) { v6 = load_image(stream, needVerify); if ( !v6 ) { system("nvram set flashing=1"); system("nvram commit"); v6 = for_each_file(stream, flash_mtd_callback, 0LL); if ( !v6 ) { system("nvram unset flashing"); system("nvram commit"); fwrite("system will reboot\n", 1u, 0x13u, stderr); reboot(0x1234567); } } fclose(stream); } else { fprintf(stderr, "can not open \"%s\" for reading\n", filename); v6 = -2; } return v6; } //----- (0000000000402754) ---------------------------------------------------- int dump_file_desc(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata) { if ( !(uint8_t)fileid ) { if ( hdr->magic != '1RDH' ) { printf("Invalid MAGIC 0x%x, 0x%x\n", hdr->magic, 827475016LL); return 0xFFFFFFEA; } printf("version %d, file type: %d\n", hdr->model, hdr->romType); } if ( userdata && strcmp(fildhdr->name, (const char *)userdata) ) return 0; printf("Segment %d: Offset 0x%x\n", (unsigned char)fileid, hdr->fileOffs[(unsigned char)fileid]); if ( fildhdr->magic == 0xBABE ) { printf("Filename %s\n", fildhdr->name); printf("Flash addr = 0x%x, length = 0x%x, partition = %d\n", fildhdr->flashaddr, fildhdr->filesize, fildhdr->mtdid); if ( userdata ) return 1; } else { printf("Invalid sub MAGIC,magic:0x%x le_mag:0x%x rsvd0:0x%x\n", fildhdr->magic, fildhdr->magic, fildhdr->rsvd0); } return 0; } //----- (00000000004028E0) ---------------------------------------------------- int command_list_files(const char *image, const char *a2) { FILE *stream; // [xsp+20h] [xbp+20h] int v6; // [xsp+2Ch] [xbp+2Ch] stream = fopen(image, "r"); if ( stream ) { v6 = for_each_file(stream, dump_file_desc, (void *)a2); if ( a2 ) { if ( v6 <= 0 ) { if ( !v6 ) v6 = -2; } else { v6 = 0; } } fclose(stream); } else { fprintf(stderr, "can not open \"%s\" for reading\n", image); v6 = -2; } return v6; } //----- (00000000004029B0) ---------------------------------------------------- int get_version_callback(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata) { char *ptr; // [xsp+50h] [xbp+50h] uint32_t size; // [xsp+58h] [xbp+58h] int size_4; // [xsp+5Ch] [xbp+5Ch] size_4 = 0; if ( fildhdr->filesize <= 7 || fildhdr->magic != 47806 ) return 0; size = fildhdr->filesize; if ( strcmp(fildhdr->name, "xiaoqiang_version") ) return size_4; if ( malloc(0x10000u) && (ptr = (char *)malloc(size)) != 0LL ) { if ( fread(ptr, 1u, size, f) == size ) { printf("%s", ptr); size_4 = 1; } else { size_4 = -5; } free(ptr); } else { fwrite("malloc failed\n", 1u, 0xEu, stderr); size_4 = -12; } return size_4; } //----- (0000000000402B20) ---------------------------------------------------- int command_get_image_version(const char *a1) { FILE *stream; // [xsp+20h] [xbp+20h] int v4; // [xsp+2Ch] [xbp+2Ch] stream = fopen(a1, "r"); if ( stream ) { v4 = for_each_file(stream, get_version_callback, 0LL); if ( v4 <= 0 ) { if ( !v4 ) v4 = -2; } else { v4 = 0; } fclose(stream); } else { fprintf(stderr, "can not open \"%s\" for reading\n", a1); v4 = -2; } return v4; } //----- (0000000000402BE0) ---------------------------------------------------- int command_get_ssh_key() { get_ssh_key(); return 0; } //----- (0000000000402C78) ---------------------------------------------------- unsigned int crc32_update(uint8_t *buf, int64_t size, unsigned int state) { while ( size ) { state = crc32_table[(unsigned char)(*buf ^ state)] ^ (state >> 8); --size; ++buf; } return state; } //----- (0000000000402CF4) ---------------------------------------------------- uint32_t calc_crc32(FILE *f, int start, unsigned int size) { uint32_t result; // w0 unsigned int v6; // [xsp+24h] [xbp+24h] uint8_t *ptr; // [xsp+28h] [xbp+28h] unsigned int chunk_size; // [xsp+34h] [xbp+34h] unsigned int crc; // [xsp+3Ch] [xbp+3Ch] crc = -1; ptr = malloc(0x10000u); if ( ptr ) { fseek(f, start, 0); while ( size ) { v6 = fread(ptr, 1u, 0x10000u, f); if ( size < v6 ) chunk_size = size; else chunk_size = v6; crc = crc32_update(ptr, chunk_size, crc); size -= chunk_size; if ( feof(f) && size ) { fwrite("File too short while required CRC length too long\n", 1u, 0x32u, stderr); return 1; } } free(ptr); rewind(f); result = crc; } else { fwrite("malloc failed\n", 1u, 0xEu, stderr); result = 1; } return result; } //----- (0000000000402E4C) ---------------------------------------------------- int64_t init_pkey(EVP_MD_CTX *ctx, RSA **pem, EVP_PKEY **ppkey, int isSsh) { int64_t result; // x0 const EVP_MD *algo; // x0 FILE *stream; // [xsp+38h] [xbp+38h] if ( isSsh == 1 ) stream = fopen("/usr/share/xiaoqiang/public_ssh.pem", "rb"); else stream = fopen("/usr/share/xiaoqiang/public.pem", "rb"); if ( stream ) { *pem = PEM_read_RSA_PUBKEY(stream, 0LL, 0LL, 0LL); if ( *pem ) { fclose(stream); *ppkey = EVP_PKEY_new(); if ( *ppkey ) { if ( EVP_PKEY_set1_RSA(*ppkey, *pem) == 1 ) { EVP_MD_CTX_init(ctx); algo = EVP_sha1(); if ( EVP_DigestInit_ex(ctx, algo, 0LL) == 1 ) { result = 0LL; } else { fwrite("error EVP_VerfyInit_ex\n", 1u, 0x17u, stderr); RSA_free(*pem); EVP_PKEY_free(*ppkey); result = 0xFFFFFFFFLL; } } else { fwrite("error EVP_PKEY_st1_RSA\n", 1u, 0x17u, stderr); RSA_free(*pem); EVP_PKEY_free(*ppkey); result = 0xFFFFFFFFLL; } } else { fwrite("error EVP_PEKY_new\n", 1u, 0x13u, stderr); RSA_free(*pem); result = 0xFFFFFFFFLL; } } else { fwrite("error PEM_read_RSAPublicKey\n", 1u, 0x1Cu, stderr); fclose(stream); result = 0xFFFFFFFFLL; } } else { fwrite("error fopen public key \n", 1u, 0x18u, stderr); result = 0xFFFFFFFFLL; } return result; } //----- (000000000040307C) ---------------------------------------------------- int j_verify_rsa(FILE *f, unsigned int start, unsigned int size, const unsigned char *sigbuf, unsigned int siglen, unsigned int isSsh) { return verify_rsa(f, start, size, sigbuf, siglen, isSsh); } //----- (00000000004030C0) ---------------------------------------------------- int verify_rsa(FILE *f, int start, unsigned int size, const unsigned char *sigbuf, unsigned int siglen, unsigned int isSsh) { int result; // w0 EVP_PKEY *pkey; // [xsp+30h] [xbp+30h] BYREF RSA *pem; // [xsp+38h] [xbp+38h] BYREF EVP_MD_CTX ctx; // [xsp+40h] [xbp+40h] BYREF unsigned int v15; // [xsp+74h] [xbp+74h] void *buf; // [xsp+78h] [xbp+78h] size_t cnt; // [xsp+84h] [xbp+84h] unsigned int v18; // [xsp+88h] [xbp+88h] int v19; // [xsp+8Ch] [xbp+8Ch] v18 = size; cnt = 0; pkey = 0LL; buf = malloc(0x10000u); if ( buf ) { v19 = init_pkey(&ctx, &pem, &pkey, isSsh); if ( v19 ) { fwrite("malloc failed\n", 1u, 0xEu, stderr); result = 1; } else { fseek(f, start, 0); while ( v18 ) { v15 = fread(buf, 1u, 0x10000u, f); if ( v18 < v15 ) cnt = v18; else cnt = v15; if ( EVP_DigestUpdate(&ctx, buf, cnt) != 1 )// EVP_VerifyUpdate { fwrite("error EVP_VerifyUpdate\n", 1u, 0x17u, stderr); v19 = 1; goto finish; } v18 -= cnt; if ( feof(f) && v18 ) { fwrite("File too short while required RSA length too long\n", 1u, 0x32u, stderr); v19 = 1; goto finish; } } if ( EVP_VerifyFinal(&ctx, sigbuf, siglen, pkey) == 1 ) { v19 = 0; } else { fwrite("error EVP_VerifyFinal\n", 1u, 0x16u, stderr); v19 = 1; } finish: rewind(f); free(buf); RSA_free(pem); EVP_PKEY_free(pkey); EVP_MD_CTX_cleanup(&ctx); result = v19; } } else { fwrite("malloc failed\n", 1u, 0xEu, stderr); result = 1; } return result; } //----- (0000000000403318) ---------------------------------------------------- int64_t write_buf(int fd, void *buf, unsigned int size) { signed int i; // [xsp+2Ch] [xbp+2Ch] for ( i = 0; i < (int)size; i += write(fd, (char *)buf + i, size - i) ) ; return size; } //----- (0000000000403394) ---------------------------------------------------- int open_and_erase_mtd(unsigned int mtdId) { char v3[16]; // [xsp+20h] [xbp+20h] BYREF unsigned int i; // [xsp+30h] [xbp+30h] BYREF unsigned int v5; // [xsp+34h] [xbp+34h] char v6[8]; // [xsp+38h] [xbp+38h] BYREF unsigned int v7; // [xsp+40h] [xbp+40h] unsigned int v8; // [xsp+44h] [xbp+44h] int fd; // [xsp+5Ch] [xbp+5Ch] memset(v3, 0, sizeof(v3)); sprintf(v3, "/dev/mtd%d", mtdId); printf("target mtd %s\n", v3); fd = open(v3, 2); ioctl(fd, 0x80204D01uLL, v6); printf("MTD Type: %x\nMTD total size: %x bytes\nMTD erase size: %x bytes\n", (unsigned char)v6[0], v7, v8); v5 = v8; printf("Beging Eraseing Block %#x\n", i); for ( i = 0; i < v7; i += v5 ) { ioctl(fd, 0x40084D06uLL, &i); ioctl(fd, 0x40084D02uLL, &i); } lseek(fd, 0LL, 0); puts("End..."); return fd; } //----- (00000000004034BC) ---------------------------------------------------- int64_t calcMd5(unsigned char *a1, const char *a2) { size_t v2; // w0 MD5_CTX v6; // [xsp+20h] [xbp+20h] BYREF if ( MD5_Init(&v6) ) { v2 = strlen(a2); if ( MD5_Update(&v6, a2, v2) ) { if ( MD5_Final(a1, &v6) ) return 0LL; puts("MD5_Final error"); } else { puts("MD5_Update error"); } } else { puts("MD5_Init error"); } return 0xFFFFFFFFLL; } //----- (000000000040355C) ---------------------------------------------------- int64_t transpostGuid(uint8_t *a1, char *outbuf) { char *v2; // x0 int64_t result; // x0 char mat[8][32]; // [xsp+28h] [xbp+28h] BYREF size_t n; // [xsp+12Ch] [xbp+12Ch] char *curRow; // [xsp+130h] [xbp+130h] int rowI; // [xsp+138h] [xbp+138h] unsigned int row; // [xsp+13Ch] [xbp+13Ch] char a9[32]; // [xsp+140h] [xbp+140h] BYREF row = 0; rowI = 0; n = 0; memset(mat, 0, sizeof(mat)); while ( *a1 ) { if ( *a1 == '-' ) { a9[32 * row++ - 0x118 + rowI] = 0; rowI = 0; } else { a9[32 * row - 0x118 + rowI++] = *a1; } ++a1; } a9[32 * row - 0x118 + rowI] = 0; curRow = outbuf; while ( 1 ) { result = row; if ( (row & 0x80000000) != 0 ) break; n = strlen(mat[row]); strncpy(curRow, mat[row], n); curRow += (int)n; if ( row ) { v2 = curRow++; *v2 = '-'; } else { *curRow = 0; } --row; } return result; } //----- (00000000004036EC) ---------------------------------------------------- int64_t get_ssh_key() { char magic[100]; // [xsp+EA8h] [xbp+18h] BYREF char snStr[100]; // [xsp+F10h] [xbp+80h] BYREF char Sn[100]; // [xsp+F78h] [xbp+E8h] BYREF unsigned char md5Output[16]; // [xsp+FE0h] [xbp+150h] BYREF FILE *stream; // [xsp+FF0h] [xbp+160h] int i; // [xsp+FFCh] [xbp+16Ch] memset(md5Output, 0, 16); memset(Sn, 0, 100); memset(snStr, 0, 100); memset(magic, 0, 100); stream = popen("nvram get SN", "r"); if ( !stream ) return puts("Failed to run command"); while ( fgets(Sn, 100, stream) ) sscanf(Sn, "%s", snStr); pclose(stream); transpostGuid("d44fb0960aa0-a5e6-4a30-250f-6d2df50a", magic); sprintf(Sn, "%s%s", snStr, magic); calcMd5(md5Output, Sn); memset(Sn, 0, sizeof(Sn)); for ( i = 0; i <= 3; ++i ) printf("%x%x", (md5Output[i] >> 4) & 0xF, md5Output[i] & 0xF); return puts(Sn); } //----- (00000000004038A4) ---------------------------------------------------- int extract_ssh_rom_callback(MiRomHdr *hdr, int64_t fileid, MiRomFile *fildhdr, FILE *f, void *userdata) { return 1; } // nfuncs=134 queued=28 decompiled=28 lumina nreq=0 worse=0 better=0 // ALL OK, 28 function(s) have been successfully decompiled