// 插件可以从plugins.cfg文件中,被传进一个整型参数。 // 当按下不同的热键或者菜单时,您需要一个插件做不同 // 的事情时,这非常有用。 void __stdcall IDAP_run(int arg) { // 插件的实体 //在LOG中显示一个字符串 char *lpInBuf = NULL; char *lpTmpBuf = NULL; char *lpFilePath = NULL; char szValue[MAXSTR + 1] = ""; char szInValue[MAXSTR + 1] = ""; // char szTmp[100] = {0}; int nPatchLogFlags = 1; uval_t nAddres = get_screen_ea(); asize_t nCount = 1; USHORT nWriteRadio = 0; //单选按钮 USHORT nSerializeRadio = -1; //单选按钮 USHORT checkmask = 0; asize_t j = 0; asize_t i = 0; // qstrncpy(szInValue,"",sizeof(szInValue)); if(AskUsingForm_c(dialog, szInValue, &nAddres, &nCount, &nWriteRadio, &nSerializeRadio, &checkmask) == 1) { if(checkmask & 1) { nAddres = get_screen_ea(); } size_t len = strlen(szInValue); for(i = 0; i < len; i++) { if(szInValue[i] != ' ') { szValue[j++] = szInValue[i]; } } len = strlen(szValue); size_t nHexLen = len / 2; if(!len) { if( lpFilePath = askfile_cv(0, "*.*", "OpenPath", 0)) { FILE* handle = fopen(lpFilePath, "rb"); if(handle == NULL) { warning("打开文件失败 Error!\n"); return; } fseek(handle, 0, SEEK_END); nHexLen = ftell(handle); fseek(handle, 0, SEEK_SET); lpTmpBuf = (char *)malloc(nHexLen + 1); memset(lpTmpBuf, 0, nHexLen + 1); fread(lpTmpBuf, 1, nHexLen, handle); fclose(handle); strcpy(szValue, lpFilePath); } else { warning("请输入数据"); return; } } else if(len % 2) { warning("数据长度不是2的倍数"); return; } else { for(i = 0;i < len;i++) { if(!isxdigit(szValue[i])) { warning("数据中含有非16进制值"); return; } } lpTmpBuf = (char *) malloc(nHexLen * 2 + 1); memset(lpTmpBuf, 0, nHexLen * 2 + 1); for(i = 0; i < nHexLen; i++) { sscanf(&szValue[i * 2],"%02x",lpTmpBuf + i); } } if(nSerializeRadio >= 0) { asize_t nSerializeSize = (nSerializeRadio + 1) * 4; asize_t nSerializeCount = nHexLen * nCount / nSerializeSize; for(i = 0; i < nSerializeCount; i++) { reversedbuf((unsigned char*)lpTmpBuf + nSerializeSize *i, nSerializeSize); } } lpInBuf = (char*)malloc(nHexLen * nCount * 2 + 1); memset(lpInBuf, 0, nHexLen * nCount * 2 + 1); for(i = 0; i < nCount; i++) { memcpy(lpInBuf + i * nHexLen, lpTmpBuf, nHexLen); } free(lpTmpBuf); msg("==============修补数据库数据==============\n"); msg("String Value = %s\n",szValue); #ifdef __EA64__ msg("Addres:0x%llX ValueSize = 0x%llX Index:%d check = %d\n",nAddres, nHexLen, nCount,checkmask); #else msg("Addres:0x%08X ValueSize = 0x%08X Index:%d check = %d\n",nAddres, nHexLen, nCount,checkmask); #endif if(!nWriteRadio) { msg("WriteData \n",nWriteRadio); } else { msg("XorWrite Data \n",nWriteRadio); } if( nHexLen * nCount > 0x100) { nPatchLogFlags = askyn_c(0, "%s", "是否打印日志!(默认不打印)\n因为数据量过大会影响IDA会假死!\nNo或Cancel表示不打印日志!\n"); } //////////////////// uint32 nSum = 0; uchar *mem = NULL; if(isLoaded(nAddres) && isLoaded(nAddres + nCount * nHexLen - 1)) { mem = (uchar *)malloc(nCount * nHexLen + 1); if(mem == NULL) { warning("malloc 函数执行失败!"); return; } get_many_bytes(nAddres,mem, nCount * nHexLen); if(nPatchLogFlags > 0) { msg("原始数据:\n"); for(i = 0; i < nCount * nHexLen; i++) { msg("%02X", mem[i]); } msg("\n"); } } else { if(!isLoaded(nAddres)) { warning("数据地址错误: 0x%p",nAddres); } else { warning("写入数据长度过大"); } return; } /////////////////////////// // long nValue = 0; for(j = 0;j < nCount;j++) { for(i = 0;i < nHexLen; i++) { // memcpy(szTmp,&szInValue[j * len + i * 2],2); //sscanf(&szValue[i * 2],"%02x",&nValue); if(nWriteRadio == 1) { lpInBuf[nSum] ^= mem[nSum]; } mem[nSum++] = lpInBuf[nSum]; } } put_many_bytes(nAddres, mem, nSum); if(nPatchLogFlags > 0) { msg("补丁数据:\n"); for(i = 0; i < nSum; i++) { msg("%02X", mem[i]); } msg("\n"); } refresh_idaview_anyway(); //刷新反汇编窗口 free(mem); free(lpInBuf); } return; }
// Plug-in process void CORE_Process(int iArg) { try { char version[16]; sprintf(version, "%u.%u", HIBYTE(MY_VERSION), LOBYTE(MY_VERSION)); msg("\n>> WhatAPIs: v: %s, built: %s, By Sirmabus\n", version, __DATE__); if (!autoIsOk()) { msg("** Must wait for IDA to finish processing before starting plug-in! **\n*** Aborted ***\n\n"); return; } // Show UI refreshUI(); int uiResult = AskUsingForm_c(mainDialog, version, doHyperlink); if (!uiResult) { msg(" - Canceled -\n"); return; } WaitBox::show(); TIMESTAMP startTime = getTimeStamp(); // Build import segment bounds table { msg("Import segments:\n"); refreshUI(); SEGLIST segList; for (int i = 0; i < get_segm_qty(); i++) { if (segment_t *s = getnseg(i)) { if (s->type == SEG_XTRN) { char buffer[64] = { "unknown" }; buffer[SIZESTR(buffer)] = 0; get_true_segm_name(s, buffer, SIZESTR(buffer)); msg(" [%d] \"%s\" "EAFORMAT" - "EAFORMAT"\n", segmentCount, buffer, s->startEA, s->endEA); BOUNDS b = { s->startEA, s->endEA }; segList.push_back(b); segmentCount++; } } } refreshUI(); // Flatten list into an array for speed if (segmentCount) { UINT size = (segmentCount * sizeof(BOUNDS)); if (segmentPtr = (BOUNDS *)_aligned_malloc(size, 16)) { BOUNDS *b = segmentPtr; for (SEGLIST::iterator i = segList.begin(); i != segList.end(); i++, b++) { b->startEA = i->startEA; b->endEA = i->endEA; } } else { msg("\n*** Allocation failure of %u bytes! ***\n", size); refreshUI(); } } } if (segmentCount) { // Make a list of all import names if (int moduleCount = get_import_module_qty()) { for (int i = 0; i < moduleCount; i++) enum_import_names(i, importNameCallback); char buffer[32]; msg("Parsed %s module imports.\n", prettyNumberString(moduleCount, buffer)); refreshUI(); } // Iterate through all functions.. BOOL aborted = FALSE; UINT functionCount = get_func_qty(); char buffer[32]; msg("Processing %s functions.\n", prettyNumberString(functionCount, buffer)); refreshUI(); for (UINT n = 0; n < functionCount; n++) { processFunction(getn_func(n)); if (WaitBox::isUpdateTime()) { if (WaitBox::updateAndCancelCheck((int)(((float)n / (float)functionCount) * 100.0f))) { msg("* Aborted *\n"); break; } } } refresh_idaview_anyway(); WaitBox::hide(); msg("\n"); msg("Done. %s comments add/appended in %s.\n", prettyNumberString(commentCount, buffer), timeString(getTimeStamp() - startTime)); msg("-------------------------------------------------------------\n"); } else msg("\n*** No import segments! ***\n"); if (segmentPtr) { _aligned_free(segmentPtr); segmentPtr = NULL; } apiMap.clear(); } CATCH() }