在我要进行逆向工程的程序中,最初IDA仅创建了三个段:CODEDATA.idata。第30-78行),我确定(至少)四个段中的实际数据是串联的,分别为DATAINITDATAEXITDATABSS。 / dword)和适当的边界;虽然所有数据都出现在正确的段边界内,但对DATA段中现在在BSS中的所有引用现在都完全弄糟了:

CODE:00401A8A                 push    ds:globalErrorMessagesCaption[eax*4] ; lpCaption


节标题为

CODE:00401A8A                 push    dword ptr ds:(algn_481049+187h)[eax*4] ; lpCaption


这里出了什么问题,怎么解决?

#1 楼

简短答案:您新创建的细分可能具有无效的选择器值0,并且只要将选择器设置为有效值(例如,在命令提示符下为SetSegmentAttr(here, SEGATTR_SEL, 1)),事情就应该重新开始工作。原因是IDA为PE32(+)创建的所有选择器都具有相同的基数,并且大多数都是等效的。

长答案:通过用户界面进行段编辑的版本。通过UI进行细分编辑可能会导致复杂的操作,因此产生的行为并不总是直观的。这就是为什么我不想在UI操作方面给出解决方案的原因。标志值的符号名称,例如SEGMOD_KEEP)。对于棘手的东西,我发现在代码片段编辑器(Shift-F2)中将自己的操作编写为命名片段最为方便。在操作结束时使用适当的Jump()-将光标定位在下一个操作的最有可能的候选对象上-这样就可以轻松地立即完成很多工作。

IDC / Python段编辑功能的文档功能比整个UI更好,并且更简单,它们更容易通过实验获得处理。而且更不容易出现令人讨厌的惊喜。如果发生了不好的事情(例如您的情况),通常可以通过使用以下命令在一个IDA实例中探查一个工作示例来对其进行修复:到另一个包含“患者”的IDA实例并输入新发现的值:

GetSegmentAttr(here, SEGATTR_FLAGS)


由于两个IDA实例共享相同的命令提示符历史记录,因此输入第二条命令就像单击向上箭头并修改在另一个IDA实例中输入的查询一样简单。如果您将新创建的段的SEGATTR_SEL设置为与现有(因此正确配置)的段相同的值,则事情可能会再次开始工作。要查找魔术标记及其名称,我更喜欢grep$(IDA)/idc/idc.idc而不是查阅帮助文件,因为idc.idc往往更全面,更及时。不会自行刷新,但是可以通过再次按下热键(例如,“ Program Segmentation”的Shift-F7)以及在命令提示符下输入“ RefreshLists()”来刷新它们。另外,我在这里写的所有内容可能都不是最佳选择,但是基于我有限的知识和现有文档,这是我能够做到的最好的选择。对于PE32(+)目标而言,它们具有平坦的地址空间非常重要。我发现它们对于将代码范围标记为属于某个模块(例如“ CRT”,“ Lua”等)很方便,但实际上并不需要创建源代码中包含的段的真实表示,因为主要是为了链接程序的好处,最终被合并为少量的PE部分。

评论


幸运的是,我做了一个备份并还原了它-如何以“正确”的方式使用IDC进行分段拆分?

–天网
2014年12月30日,2:15

#2 楼

除非该段具有有效的选择器,否则IDA不能引用该段中的符号,因此这是为新段设置的最重要的属性。可以通过“段落中的基础”字段在“创建细分...”对话框中设置选择器。

GetSegmentAttr(here, SEGATTR_SEL)告诉您正确的选择器是什么,如果光标在要分割的段中。您可以在对话框的输入字段中直接输入表达式。同样,您可以在开始地址字段中键入here,在结束地址字段中键入SegEnd(here)。相关属性(包括SEGATTR_SEL):


CompileEx(
  "class HelperFunctions {"
    "copy_seg_attr (src, dst, attr) { SetSegmentAttr(dst, attr, GetSegmentAttr(src, attr)); }"
  "};", 0  );

auto ori_seg, ok, fn;

ori_seg = SegStart(here);

ok = AddSegEx(
   here, 
   SegEnd(here), 
   GetSegmentAttr(here, SEGATTR_SEL),
   GetSegmentAttr(here, SEGATTR_BITNESS),
   GetSegmentAttr(here, SEGATTR_ALIGN),
   GetSegmentAttr(here, SEGATTR_COMB),
   ADDSEG_NOSREG  );

if (!ok)  return Warning("AddSegEx() failed");

fn = HelperFunctions();    
fn.copy_seg_attr(ori_seg, here, SEGATTR_PERM);
fn.copy_seg_attr(ori_seg, here, SEGATTR_FLAGS);
fn.copy_seg_attr(ori_seg, here, SEGATTR_ES);
fn.copy_seg_attr(ori_seg, here, SEGATTR_SS);
fn.copy_seg_attr(ori_seg, here, SEGATTR_DS);
fn.copy_seg_attr(ori_seg, here, SEGATTR_TYPE);
fn.copy_seg_attr(ori_seg, here, SEGATTR_COLOR);

RenameSeg(here, AskStr("", "segment name"));


注意:我发现的唯一技巧是通过Compile()或CompileEx()内联类定义用于在代码段内定义函数。不过,它似乎仅在较新的IDA(使用6.6和6.7测试)中有效,并且仅当Compile()在代码片段开头正确时才起作用。

对于较旧的IDA版本,辅助函数必须以其他方式定义,例如在单独的.idc文件中,并且对AddSegEx()的调用需要用AddSeg()代替。 br />
此外,我找不到查询段类的方法,因此即使有可以设置它的函数SetSegClass()也无法将其复制。操作-将下一个分段合并到当前分段中-更为简单:每个段,这对于内存转储很方便。或用于消除意外的分段分割...