除非该段具有有效的选择器,否则 IDA 无法引用该段中的符号,因此这是为新段设置的最重要的属性。选择器可以在“创建段...”对话框中通过“段落基础”字段进行设置。
GetSegmentAttr(here, SEGATTR_SEL)
如果光标位于要拆分的段中,则告诉您正确的选择器是什么。您可以在对话的输入字段中直接输入表达式;出于同样的原因,您可以here
在开始地址字段和SegEnd(here)
结束地址字段中输入。
这是一个 IDC 片段 (Shift-F2),它在当前位置拆分当前段,克隆最相关的属性(包括 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()。
另外,我找不到查询段类的方法,因此即使有SetSegClass()
可以设置它的函数也无法复制它。
逆操作——将下一段合并到当前段——要简单得多:
auto seg_beg, seg_end, next_seg;
seg_beg = SegStart(here);
if (seg_beg == -1) return Warning("no segment here");
next_seg = NextSeg(here);
if (next_seg == SegEnd(here))
{
seg_end = SegEnd(next_seg);
DelSeg(next_seg, SEGMOD_KEEP);
SetSegBounds(seg_beg, seg_beg, seg_end, SEGMOD_KEEP);
Jump(PrevNotTail(seg_end));
}
使用这样的代码段,您只需单击每个段即可合并一整船段,这对于内存转储非常方便。或者为了撤销意外的段拆分......