实验要求
每个实验阶段考察ELF文件组成与程序链接过程的不同方面知识。
实验所用
工具
*主机与虚拟机之间的共享文件夹(为了便于在主机与虚拟机之间高效地传输文件,启用一个共享文件夹是较为便捷的做法。设置共享文件夹的具体方法敬请参考CSDN其他博主撰写的详细教程)
*IDA(查看需要修改的.o文件或链接生成的可执行文件的伪代码或汇编语言,起到辅助理解文件结构与功能或检查修改后文件结构与功能是否正常等作用。但请务必注意IDA标注的地址可能并不符合实际,如果要确定某个指令的准确地址请查看使用objdump生成的反汇编文件)
*010 editor(010 editor是一个十六进制编辑器,它可以用来查看和编辑二进制文件。我选择使用它来替代Vim。由于各种原因,在此本人就不放置下载链接了,各位自行上网搜索即可)
010 editor超基础用法
在Windows系统上下载010 editor后,用它打开需要修改的.o文件,会弹出如下图所示的界面。
我的操作步骤是先借助IDA确定待修改的字符串,随后运用010 Editor的查找功能定位到相同的区域。因为虽然IDA与010 Editor所示的地址有出入,但它们所指向的数据内容是一致的。
点击查找选项并在弹出的对话框内输入目标字符串,010 Editor将会自动高亮并标识出所有匹配的字符串并在界面下方显示查找结果。
接下来便可以进行字符串的修改操作。但需要留意的是,在使用010 Editor进行修改时,请确保选择替换模式而非插入模式,因为插入操作可能会打乱原有的内存地址布局。此外,建议暂时关闭中文输入法以避免不必要的干扰。
实验思考与结果
phase1.o
修改phase1.o的数据段内容,使其与main.o链接后运行能够输出自己的学号。
/*do_phase的伪代码*/
int do_phase()
{
int result; // eax
puts(s);
result = notify;
if ( notify == 1 )
return client(1, s);
return result;
}
/*修改前char s[]的内容*/
.data:08000083 ; char s[]
.data:08000083 62 09 46 63 44 75 70 34 51 38+s db
'b',9,'FcDup4Q8mmFO0of54ZLfZU12PnSSKbIHVv3zpvow7XErH17RyTPsGcwg'
,9,'Qz4QZqXT1UQG5OF1TgUlWeNldWaJ'
.data:08000083 6D 6D 46 4F 30 6F 66 35 34 5A+ ; DATA XREF: do_phase+6↑o
.data:08000083 4C 66 5A 55 31 32 50 6E 53 5 ; do_phase+21↑o
.data:08000083 4B 62 49 48 56 76 33 7A 70 76+db '2lvMEGpy9P uwXQsGCYuHpxRFrq',0
/*修改后char s[]的内容*/
.data:08000083 ; char s[]
.data:08000083 ** ** ** ** ** ** ** ** ** **+s db '学号',0
; DATA XREF: do_phase+6↑o
.data:08000083 00 ; do_phase+21↑o
.data:0800008E 6D 46 4F 30 6F 66 35 34 5A 4C+aMfo0of54zlfzu1 db
'mFO0of54ZLfZU12PnSSKbIHVv3zpvow7XErH17RyTPsGcwg'
,9,'Qz4QZqXT1UQG5OF1TgUlWeNldWaJ2lvMEGpy9P uwXQ'
.data:0800008E 66 5A 55 31 32 50 6E 53 53 4B+db 'sGCYuHpxRFrq',0
phase2.o
/*修改前do_phase函数的伪代码*/
void do_phase()
{
;
}
/*修改前的do_phase函数*/
.text:08000038 ; void do_phase()
.text:08000038 public do_phase
.text:08000038 do_phase proc near ; DATA XREF: .data:phase↓o
.text:08000038 ; .eh_frame:080000A4↓o
.text:08000038 ; __unwind {
.text:08000038 55 push ebp
.text:08000039 89 E5 mov ebp, esp
.text:0800003B 90 nop
.text:0800003C 90 nop
.text:0800003D 90 nop
.text:0800003E 90 nop
.text:0800003F 90 nop
.text:08000040 90 nop
.text:08000041 90 nop
.text:08000042 90 nop
.text:08000043 90 nop
.text:08000044 90 nop
.text:08000045 90 nop
.text:08000046 90 nop
.text:08000047 90 nop
.text:08000048 90 nop
.text:08000049 90 nop
.text:0800004A 90 nop
.text:0800004B 90 nop
.text:0800004C 90 nop
.text:0800004D 90 nop
.text:0800004E 90 nop
.text:0800004F 90 nop
.text:08000050 90 nop
.text:08000051 90 nop
.text:08000052 90 nop
.text:08000053 90 nop
.text:08000054 90 nop
.text:08000055 90 nop
.text:08000056 90 nop
.text:08000057 90 nop
.text:08000058 90 nop
.text:08000059 90 nop
.text:0800005A 90 nop
.text:0800005B 90 nop
.text:0800005C 5D pop ebp
.text:0800005D C3 retn
.text:0800005D ; } // starts at 8000038
.text:0800005D do_phase endp
因为phase2.o中函数包含一个名为DPMeZyaD的函数,它可以实现输出字符串并调用评分函数client的功能。因此,我们需要修改do_phase函数使之能够把学号作为参数传递给DPMeZyaD函数并调用它。
/* DPMeZyaD函数的伪代码*/
void __cdecl __noreturn DPMeZyaD(char *s)
{
puts(s);
if ( notify == 1 )
client(2, s);
exit(1);
}
那么将do_phase函数开头的nop指令修改为:
/*修改后do_phase函数的伪代码,"**********"代表学号*/
void __noreturn do_phase()
{
char v0[12]; // [esp-Ch] [ebp-Ch] BYREF
v0[11] = 0;
strcpy(v0, "**********");
DPMeZyaD(v0);
}
/*修改后的do_phase函数*/
.text:08000038 public do_phase
.text:08000038 do_phase proc near ; DATA XREF: .data:phase↓o
.text:08000038 ; .eh_frame:080000A4↓o
.text:08000038 ; __unwind {
.text:08000038 55 push ebp
.text:08000039 89 E5 mov ebp, esp
.text:0800003B 68 ** ** 00 00 push ****h
.text:08000040 68 ** ** ** ** push ********h
.text:08000045 68 ** ** ** ** push ********h
.text:0800004A 54 push esp ; s
.text:0800004B E8 B0 FF FF FF call DPMeZyaD
.text:0800004B do_phase endp
.text:0800004B ; -------------------------------------------------------------
.text:08000050 90 90 90 90 90 90 90 90 90 90+db 0Ch dup(90h)
.text:0800005C ; -------------------------------------------------------------
.text:0800005C 5D pop ebp
.text:0800005D C3 retn
.text:0800005D ; } // starts at 8000038
.text:0800005D
.text:0800005D _text ends
通过在栈中压入格式为“学号\0\0”的字符串,构建出满足要求的包含学号的字符数组,并将指向该字符串起始地址的esp寄存器值作为参数传递给DPMeZyaD函数调用,即可实现链接后正确输出学号的功能。
解答此题的关键在于理解当一个字符数组作为参数传递给另一个函数时,实际上传递的是该字符串的首地址。此外,将字符串压入栈中的顺序也至关重要,这一顺序与栈数据结构的“后进先出”特性密切相关。
phase3.o
利用符号解析中的强弱符号规则,新建一个phase3_patch.o(命名必须为此),使其与main.o和phase3.o链接后,运行输出学号。
/*do_phase函数的伪代码*/
unsigned int do_phase()
{
unsigned int i; // [esp+0h] [ebp-28h]
char v2[22]; // [esp+6h] [ebp-22h] BYREF
unsigned int v3; // [esp+1Ch] [ebp-Ch]
v3 = __readgsdword(0x14u);
strcpy(v2, "afugnyblch");
v2[11] = 0;
for ( i = 0; i <= 9; ++i )
{
v2[i + 11] = YHGrOkWiUr[(unsigned __int8)v2[i]];
putchar(v2[i + 11]);
}
v2[i + 11] = 0;
if ( notify == 1 )
client(3, &v2[11]);
return __readgsdword(0x14u) ^ v3;
}
由do_phase函数的伪代码中的“putchar(v2[i + 11]);”和“client(3, &v2[11]);”等可知,要通过操作使得从数组v2的第11个元素开始填入字符串“学号\0”。
/*phase3.o中未被初始化的YHGrOkWiUr数组*/
===========================================================================
common:080000F8 ; Segment type: Communal definitions
common:080000F8 ; common
common:080000F8 00 01 00 00 comm YHGrOkWiUr:byte:100h ; DATA XREF: do_phase+
===========================================================================
又因为“strcpy(v2,"afugnyblch");”和“v2[i + 11] = YHGrOkWiUr[(unsigned __int8)v2[i]];”,所以在phase3_patch.o文件中我们需要构造一个初始化完备的YHGrOkWiUr数组,运用符号解析中的强弱符号规则来替代原phase3.o文件中未被初始化的同名数组。并且我们还需要通过分析数组v2与YHGrOkWiUr元素间的映射关系,确定组成学号的各个数字在数组中的具体位置。
鉴于直接编辑.o文件可行性较低,我们可以编写一个初始化了YHGrOkWiUr数组的.c源文件,并通过gcc编译成对应的.o目标文件。随后将此新生成的目标文件与原有的main.o和phase3.o进行链接,如此一来,在运行程序时即可成功输出学号信息。
/* 输入0是为了填充空位,'*'表示组成学号的数字 */
char YHGrOkWiUr[] = {
0,//这个额外的0字节是为了确保程序遵循字节对齐原则
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'*', '*', '*', 0, 0, '*', '*','*', 0, 0, 0, '*', 0, '*', 0, 0,
0, 0, 0, 0, '*', 0, 0, 0, '*', 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
/*这是phase3_patch.o文件中所包含的YHGrOkWiUr数组的具体内容*/
.data:08000020 public YHGrOkWiUr
.data:08000020 00 YHGrOkWiUr db 0
.data:08000021 00 db 0
.data:08000022 00 db 0
.data:08000023 00 db 0
.data:08000024 00 db 0
.data:08000025 00 db 0
.data:08000026 00 db 0
.data:08000027 00 db 0
.data:08000028 00 db 0
.data:08000029 00 db 0
.data:0800002A 00 db 0
.data:0800002B 00 db 0
.data:0800002C 00 db 0
.data:0800002D 00 db 0
.data:0800002E 00 db 0
.data:0800002F 00 db 0
.data:08000030 00 db 0
.data:08000031 00 db 0
.data:08000032 00 db 0
.data:08000033 00 db 0
.data:08000034 00 db 0
.data:08000035 00 db 0
.data:08000036 00 db 0
.data:08000037 00 db 0
.data:08000038 00 db 0
.data:08000039 00 db 0
.data:0800003A 00 db 0
.data:0800003B 00 db 0
.data:0800003C 00 db 0
.data:0800003D 00 db 0
.data:0800003E 00 db 0
.data:0800003F 00 db 0
.data:08000040 00 db 0
.data:08000041 00 db 0
.data:08000042 00 db 0
.data:08000043 00 db 0
.data:08000044 00 db 0
.data:08000045 00 db 0
.data:08000046 00 db 0
.data:08000047 00 db 0
.data:08000048 00 db 0
.data:08000049 00 db 0
.data:0800004A 00 db 0
.data:0800004B 00 db 0
.data:0800004C 00 db 0
.data:0800004D 00 db 0
.data:0800004E 00 db 0
.data:0800004F 00 db 0
.data:08000050 00 db 0
.data:08000051 00 db 0
.data:08000052 00 db 0
.data:08000053 00 db 0
.data:08000054 00 db 0
.data:08000055 00 db 0
.data:08000056 00 db 0
.data:08000057 00 db 0
.data:08000058 00 db 0
.data:08000059 00 db 0
.data:0800005A 00 db 0
.data:0800005B 00 db 0
.data:0800005C 00 db 0
.data:0800005D 00 db 0
.data:0800005E 00 db 0
.data:0800005F 00 db 0
.data:08000060 00 db 0
.data:08000061 00 db 0
.data:08000062 00 db 0
.data:08000063 00 db 0
.data:08000064 00 db 0
.data:08000065 00 db 0
.data:08000066 00 db 0
.data:08000067 00 db 0
.data:08000068 00 db 0
.data:08000069 00 db 0
.data:0800006A 00 db 0
.data:0800006B 00 db 0
.data:0800006C 00 db 0
.data:0800006D 00 db 0
.data:0800006E 00 db 0
.data:0800006F 00 db 0
.data:08000070 00 db 0
.data:08000071 00 db 0
.data:08000072 00 db 0
.data:08000073 00 db 0
.data:08000074 00 db 0
.data:08000075 00 db 0
.data:08000076 00 db 0
.data:08000077 00 db 0
.data:08000078 00 db 0
.data:08000079 00 db 0
.data:0800007A 00 db 0
.data:0800007B 00 db 0
.data:0800007C 00 db 0
.data:0800007D 00 db 0
.data:0800007E 00 db 0
.data:0800007F 00 db 0
.data:08000080 00 db 0
.data:08000081 00 db 0
.data:08000082 00 db 0
.data:08000083 00 db 0
.data:08000084 00 db 0
.data:08000085 00 db 0
.data:08000086 00 db 0
.data:08000087 00 db 0
.data:08000088 00 db 0
.data:08000089 00 db 0
.data:0800008A 00 db 0
.data:0800008B 00 db 0
.data:0800008C 00 db 0
.data:0800008D 00 db 0
.data:0800008E 00 db 0
.data:0800008F 00 db 0
.data:08000090 00 db 0
.data:08000091 00 db 0
.data:08000092 00 db 0
.data:08000093 00 db 0
.data:08000094 00 db 0
.data:08000095 00 db 0
.data:08000096 00 db 0
.data:08000097 00 db 0
.data:08000098 00 db 0
.data:08000099 00 db 0
.data:0800009A 00 db 0
.data:0800009B 00 db 0
.data:0800009C 00 db 0
.data:0800009D 00 db 0
.data:0800009E 00 db 0
.data:0800009F 00 db 0
.data:080000A0 00 db 0
.data:080000A1 00 db 0
.data:080000A2 00 db 0
.data:080000A3 00 db 0
.data:080000A4 00 db 0
.data:080000A5 00 db 0
.data:080000A6 00 db 0
.data:080000A7 00 db 0
.data:080000A8 00 db 0
.data:080000A9 00 db 0
.data:080000AA 00 db 0
.data:080000AB 00 db 0
.data:080000AC 00 db 0
.data:080000AD 00 db 0
.data:080000AE 00 db 0
.data:080000AF 00 db 0
.data:080000B0 00 db 0
.data:080000B1 00 db 0
.data:080000B2 00 db 0
.data:080000B3 00 db 0
.data:080000B4 00 db 0
.data:080000B5 00 db 0
.data:080000B6 00 db 0
.data:080000B7 00 db 0
.data:080000B8 00 db 0
.data:080000B9 00 db 0
.data:080000BA 00 db 0
.data:080000BB 00 db 0
.data:080000BC 00 db 0
.data:080000BD 00 db 0
.data:080000BE 00 db 0
.data:080000BF 00 db 0
.data:080000C0 00 db 0
.data:080000C1 00 db 0
.data:080000C2 00 db 0
.data:080000C3 00 db 0
.data:080000C4 00 db 0
.data:080000C5 00 db 0
.data:080000C6 00 db 0
.data:080000C7 00 db 0
.data:080000C8 00 db 0
.data:080000C9 00 db 0
.data:080000CA 00 db 0
.data:080000CB 00 db 0
.data:080000CC 00 db 0
.data:080000CD 00 db 0
.data:080000CE 00 db 0
.data:080000CF 00 db 0
.data:080000D0 00 db 0
.data:080000D1 00 db 0
.data:080000D2 00 db 0
.data:080000D3 00 db 0
.data:080000D4 00 db 0
.data:080000D5 ** db **h ; *
.data:080000D6 ** db **h ; *
.data:080000D7 ** db **h ; *
.data:080000D8 00 db 0
.data:080000D9 00 db 0
.data:080000DA ** db **h ; *
.data:080000DB ** db **h ; *
.data:080000DC ** db **h ; *
.data:080000DD 00 db 0
.data:080000DE 00 db 0
.data:080000DF 00 db 0
.data:080000E0 ** db **h ; *
.data:080000E1 00 db 0
.data:080000E2 ** db **h ; *
.data:080000E3 00 db 0
.data:080000E4 00 db 0
.data:080000E5 00 db 0
.data:080000E6 00 db 0
.data:080000E7 00 db 0
.data:080000E8 00 db 0
.data:080000E9 ** db **h ; *
.data:080000EA 00 db 0
.data:080000EB 00 db 0
.data:080000EC 00 db 0
.data:080000ED ** db **h ; *
.data:080000EE 00 db 0
.data:080000EF 00 db 0
.data:080000F0 00 db 0
.data:080000F1 00 db 0
.data:080000F2 00 db 0
.data:080000F3 00 db 0
.data:080000F4 00 db 0
.data:080000F5 00 db 0
.data:080000F6 00 db 0
.data:080000F7 00 db 0
.data:080000F8 00 db 0
.data:080000F9 00 db 0
.data:080000FA 00 db 0
.data:080000FB 00 db 0
.data:080000FC 00 db 0
.data:080000FD 00 db 0
.data:080000FE 00 db 0
.data:080000FF 00 db 0
.data:08000100 00 db 0
.data:08000101 00 db 0
.data:08000102 00 db 0
.data:08000103 00 db 0
.data:08000104 00 db 0
.data:08000105 00 db 0
.data:08000106 00 db 0
.data:08000107 00 db 0
.data:08000108 00 db 0
.data:08000109 00 db 0
.data:0800010A 00 db 0
.data:0800010B 00 db 0
.data:0800010C 00 db 0
.data:0800010D 00 db 0
.data:0800010E 00 db 0
.data:0800010F 00 db 0
.data:08000110 00 db 0
.data:08000111 00 db 0
.data:08000112 00 db 0
.data:08000113 00 db 0
.data:08000114 00 db 0
.data:08000115 00 db 0
.data:08000116 00 db 0
.data:08000117 00 db 0
.data:08000118 00 db 0
.data:08000119 00 db 0
.data:0800011A 00 db 0
.data:0800011B 00 db 0
.data:0800011C 00 db 0
.data:0800011D 00 db 0
.data:0800011E 00 db 0
.data:0800011F 00 db 0
.data:08000120 00 db 0
.data:08000121 00 db 0
.data:08000122 00 db 0
.data:08000123 00 db 0
.data:08000124 00 db 0
.data:08000125 00 db 0
.data:08000126 00 db 0
.data:08000127 00 db 0
.data:08000128 00 db 0
.data:08000129 00 db 0
.data:0800012A 00 db 0
.data:0800012B 00 db 0
.data:0800012C 00 db 0
.data:0800012D 00 db 0
.data:0800012E 00 db 0
.data:0800012F 00 db 0
.data:08000130 00 db 0
.data:08000131 00 db 0
.data:08000132 00 db 0
.data:08000133 00 db 0
.data:08000134 00 db 0
.data:08000135 00 db 0
.data:08000136 00 db 0
.data:08000137 00 db 0
.data:08000138 00 db 0
.data:08000139 00 db 0
.data:0800013A 00 db 0
.data:0800013B 00 db 0
.data:0800013C 00 db 0
.data:0800013D 00 db 0
.data:0800013E 00 db 0
.data:0800013F 00 db 0
.data:08000140 00 db 0
.data:08000141 00 db 0
.data:08000142 00 db 0
.data:08000143 00 db 0
.data:08000144 00 db 0
.data:08000145 00 db 0
.data:08000146 00 db 0
.data:08000147 00 db 0
.data:08000148 00 db 0
.data:08000149 00 db 0
.data:0800014A 00 db 0
.data:0800014B 00 db 0
.data:0800014C 00 db 0
.data:0800014D 00 db 0
.data:0800014E 00 db 0
.data:0800014F 00 db 0
.data:08000150 00 db 0
.data:08000151 00 db 0
.data:08000152 00 db 0
.data:08000153 00 db 0
.data:08000154 00 db 0
.data:08000155 00 db 0
.data:08000156 00 db 0
.data:08000157 00 db 0
.data:08000158 00 db 0
.data:08000159 00 db 0
.data:0800015A 00 db 0
.data:0800015B 00 db 0
.data:0800015C 00 db 0
.data:0800015D 00 db 0
.data:0800015E 00 db 0
.data:0800015F 00 db 0
.data:08000160 00 db 0
.data:08000161 00 db 0
.data:08000162 00 db 0
.data:08000163 00 db 0
.data:08000164 00 db 0
.data:08000165 00 db 0
.data:08000166 00 db 0
.data:08000167 00 db 0
.data:08000168 00 db 0
.data:08000169 00 db 0
.data:0800016A 00 db 0
.data:0800016B 00 db 0
.data:0800016C 00 db 0
.data:0800016D 00 db 0
.data:0800016E 00 db 0
.data:0800016F 00 db 0
.data:08000170 00 db 0
.data:08000171 00 db 0
.data:08000172 00 db 0
.data:08000173 00 db 0
.data:08000174 00 db 0
.data:08000174 _data ends
phase4.o
/*修改前do_phase函数的伪代码*/
unsigned int do_phase()
{
char v1; // [esp+Fh] [ebp-29h]
unsigned int i; // [esp+10h] [ebp-28h]
char v3[22]; // [esp+16h] [ebp-22h] BYREF
unsigned int v4; // [esp+2Ch] [ebp-Ch]
v4 = __readgsdword(0x14u);
strcpy(v3, "SYJFKAHEIO");
for ( i = 0; i <= 9; ++i )
{
v1 = v3[i];
switch ( v1 )
{
case 'A':
v1 = 56;
break;
case 'B':
v1 = 54;
break;
case 'C':
v1 = 74;
break;
case 'D':
v1 = 51;
break;
case 'E':
v1 = 49;
break;
case 'F':
v1 = 86;
break;
case 'G':
v1 = 55;
break;
case 'H':
v1 = 53;
break;
case 'I':
v1 = 85;
break;
case 'J':
v1 = 52;
break;
case 'K':
v1 = 99;
break;
case 'L':
v1 = 57;
break;
case 'M':
v1 = 111;
break;
case 'N':
v1 = 89;
break;
case 'O':
v1 = 69;
break;
case 'P':
v1 = 63;
break;
case 'Q':
v1 = 103;
break;
case 'R':
v1 = 48;
break;
case 'S':
v1 = 84;
break;
case 'T':
v1 = 126;
break;
case 'U':
v1 = 60;
break;
case 'V':
v1 = 65;
break;
case 'W':
v1 = 123;
break;
case 'X':
v1 = 90;
break;
case 'Y':
v1 = 50;
break;
case 'Z':
v1 = 68;
break;
default:
break;
}
v3[i + 11] = v1;
putchar(v3[i + 11]);
}
v3[i + 11] = 0;
if ( notify == 1 )
client(4, &v3[11]);
return __readgsdword(0x14u) ^ v4;
}
根据“掌握switch语句的重定位原理”的实验提示、“不能修改.text节”的实验要求以及do_phase函数的伪代码,再结合向AI咨询后获得的信息,我们可以知道目标应该是修改switch函数的跳转表,使"SYJFKAHEIO"能与“学号”一一对应。
/*这是do_phase函数执行“v1 = v3[i];”和“switch ( v1 )”的部分,
“sub eax,41h”、“cmp eax,19h”、“mov eax, ds:jpt_800005A[eax*4]”
和“jmp eax”可能是理解问题的关键*/
.text:08000035 loc_8000035: ; CODE XREF: do_phase+135↓j
.text:08000035 8D 55 DE lea edx, [ebp+var_22]
.text:08000038 8B 45 D8 mov eax, [ebp+var_28]
.text:0800003B 01 D0 add eax, edx
.text:0800003D 0F B6 00 movzx eax, byte ptr [eax]
.text:08000040 88 45 D7 mov [ebp+var_29], al
.text:08000043 0F BE 45 D7 movsx eax, [ebp+var_29]
.text:08000047 83 E8 41 sub eax, 41h ; 'A' ; switch 26 cases
.text:0800004A 83 F8 19 cmp eax, 19h
.text:0800004D 0F 87 B0 00 00 00 ja def_800005 ; jumptable 0800005A default case
.text:08000053 8B 04 85 80 01 00 08 mov eax, ds:jpt_800005A[eax*4]
.text:0800005A FF E0 jmp eax ; switch jump
对照跳转表和跳转部分的汇编代码可以推断,各字符与字符‘A’在ASCII码表中的差值恰好等于其对应的跳转地址相对于跳转表起始位置的偏移量。因此,为了使字符串"SYJFKAHEIO"中的每个字符都对应到正确的数字,我们需要对跳转表中,与这些字符相对应的特定位置上的跳转地址进行调整,使其指向各自对应数字的代码段。举例来说,对于字符‘S’,如果希望将字符'2'赋值给变量v1,我们就需要将其跳转地址修改为loc_80000F8,以便执行“mov [ebp+var_29], 32h”指令,也就是将rodata段中的“D4 00 00 08”修改为“F8 00 00 08”。并且因为所需的跳转目标地址都已在跳转表中列出,我们可以参考跳转表来精确地进行修改。
/*修改前的跳转表*/
.rodata:08000180 ; Segment type: Pure data
.rodata:08000180 ; Segment permissions: Read
.rodata:08000180 _rodata segment dword public 'CONST' use32
.rodata:08000180 assume cs:_rodata
.rodata:08000180 ;org 8000180h
.rodata:08000180 5C 00 00 08 65 00 00 08 6E 00+jpt_800005A dd offset loc_800005C ; DATA XREF: do_phase+53↑r
.rodata:08000180 00 08 77 00 00 08 80 00 00 08+dd offset loc_8000065 ; jump table for switch statement
.rodata:08000180 86 00 00 08 8C 00 00 08 92 00+dd offset loc_800006E
.rodata:08000180 00 08 98 00 00 08 9E 00 00 08+dd offset loc_8000077
.rodata:08000180 A4 00 00 08 AA 00 00 08 B0 00+dd offset loc_8000080
.rodata:08000180 00 08 B6 00 00 08 BC 00 00 08+dd offset loc_8000086
.rodata:08000180 C2 00 00 08 C8 00 00 08 CE 00+dd offset loc_800008C
.rodata:08000180 00 08 D4 00 00 08 DA 00 00 08+dd offset loc_8000092
.rodata:08000180 E0 00 00 08 E6 00 00 08 EC 00+dd offset loc_8000098
.rodata:08000180 00 08 F2 00 00 08 F8 00 00 08+dd offset loc_800009E
.rodata:08000180 FE 00 00 08 dd offset loc_80000A4
.rodata:08000180 dd offset loc_80000AA
.rodata:08000180 dd offset loc_80000B0
.rodata:08000180 dd offset loc_80000B6
.rodata:08000180 dd offset loc_80000BC
.rodata:08000180 dd offset loc_80000C2
.rodata:08000180 dd offset loc_80000C8
.rodata:08000180 dd offset loc_80000CE
.rodata:08000180 dd offset loc_80000D4
.rodata:08000180 dd offset loc_80000DA
.rodata:08000180 dd offset loc_80000E0
.rodata:08000180 dd offset loc_80000E6
.rodata:08000180 dd offset loc_80000EC
.rodata:08000180 dd offset loc_80000F2
.rodata:08000180 dd offset loc_80000F8
.rodata:08000180 dd offset loc_80000FE
.rodata:08000180 _rodata ends
/*修改前switch函数的26个分支的汇编代码*/
.text:0800005C loc_800005C: ; CODE XREF: do_phase+5A↑j
.text:0800005C ; DATA XREF: .rodata:jpt_800005A↓o
.text:0800005C C6 45 D7 38 mov [ebp+var_29], 38h ; '8' ; jumptable 0800005A case 65
.text:08000060 E9 9E 00 00 00 jmp def_800005A ; jumptable 0800005A default case
.text:08000060
.text:08000065 ; ---------------------------------------------------------------------------
.text:08000065
.text:08000065 loc_8000065: ; CODE XREF: do_phase+5A↑j
.text:08000065 ; DATA XREF: .rodata:jpt_800005A↓o
.text:08000065 C6 45 D7 36 mov [ebp+var_29], 36h ; '6' ; jumptable 0800005A case 66
.text:08000069 E9 95 00 00 00 jmp def_800005A ; jumptable 0800005A default case
.text:08000069
.text:0800006E ; ---------------------------------------------------------------------------
.text:0800006E
.text:0800006E loc_800006E: ; CODE XREF: do_phase+5A↑j
.text:0800006E ; DATA XREF: .rodata:jpt_800005A↓o
.text:0800006E C6 45 D7 4A mov [ebp+var_29], 4Ah ; 'J' ; jumptable 0800005A case 67
.text:08000072 E9 8C 00 00 00 jmp def_800005A ; jumptable 0800005A default case
.text:08000072
.text:08000077 ; ---------------------------------------------------------------------------
.text:08000077
.text:08000077 loc_8000077: ; CODE XREF: do_phase+5A↑j
.text:08000077 ; DATA XREF: .rodata:jpt_800005A↓o
.text:08000077 C6 45 D7 33 mov [ebp+var_29], 33h ; '3' ; jumptable 0800005A case 68
.text:0800007B E9 83 00 00 00 jmp def_800005A ; jumptable 0800005A default case
.text:0800007B
.text:08000080 ; ---------------------------------------------------------------------------
.text:08000080
.text:08000080 loc_8000080: ; CODE XREF: do_phase+5A↑j
.text:08000080 ; DATA XREF: .rodata:jpt_800005A↓o
.text:08000080 C6 45 D7 31 mov [ebp+var_29], 31h ; '1' ; jumptable 0800005A case 69
.text:08000084 EB 7D jmp short def_800005A ; jumptable 0800005A default case
.text:08000084
.text:08000086 ; ---------------------------------------------------------------------------
.text:08000086
.text:08000086 loc_8000086: ; CODE XREF: do_phase+5A↑j
.text:08000086 ; DATA XREF: .rodata:jpt_800005A↓o
.text:08000086 C6 45 D7 56 mov [ebp+var_29], 56h ; 'V' ; jumptable 0800005A case 70
.text:0800008A EB 77 jmp short def_800005A ; jumptable 0800005A default case
.text:0800008A
.text:0800008C ; ---------------------------------------------------------------------------
.text:0800008C
.text:0800008C loc_800008C: ; CODE XREF: do_phase+5A↑j
.text:0800008C ; DATA XREF: .rodata:jpt_800005A↓o
.text:0800008C C6 45 D7 37 mov [ebp+var_29], 37h ; '7' ; jumptable 0800005A case 71
.text:08000090 EB 71 jmp short def_800005A ; jumptable 0800005A default case
.text:08000090
.text:08000092 ; ---------------------------------------------------------------------------
.text:08000092
.text:08000092 loc_8000092: ; CODE XREF: do_phase+5A↑j
.text:08000092 ; DATA XREF: .rodata:jpt_800005A↓o
.text:08000092 C6 45 D7 35 mov [ebp+var_29], 35h ; '5' ; jumptable 0800005A case 72
.text:08000096 EB 6B jmp short def_800005A ; jumptable 0800005A default case
.text:08000096
.text:08000098 ; ---------------------------------------------------------------------------
.text:08000098
.text:08000098 loc_8000098: ; CODE XREF: do_phase+5A↑j
.text:08000098 ; DATA XREF: .rodata:jpt_800005A↓o
.text:08000098 C6 45 D7 55 mov [ebp+var_29], 55h ; 'U' ; jumptable 0800005A case 73
.text:0800009C EB 65 jmp short def_800005A ; jumptable 0800005A default case
.text:0800009C
.text:0800009E ; ---------------------------------------------------------------------------
.text:0800009E
.text:0800009E loc_800009E: ; CODE XREF: do_phase+5A↑j
.text:0800009E ; DATA XREF: .rodata:jpt_800005A↓o
.text:0800009E C6 45 D7 34 mov [ebp+var_29], 34h ; '4' ; jumptable 0800005A case 74
.text:080000A2 EB 5F jmp short def_800005A ; jumptable 0800005A default case
.text:080000A2
.text:080000A4 ; ---------------------------------------------------------------------------
.text:080000A4
.text:080000A4 loc_80000A4: ; CODE XREF: do_phase+5A↑j
.text:080000A4 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000A4 C6 45 D7 63 mov [ebp+var_29], 63h ; 'c' ; jumptable 0800005A case 75
.text:080000A8 EB 59 jmp short def_800005A ; jumptable 0800005A default case
.text:080000A8
.text:080000AA ; ---------------------------------------------------------------------------
.text:080000AA
.text:080000AA loc_80000AA: ; CODE XREF: do_phase+5A↑j
.text:080000AA ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000AA C6 45 D7 39 mov [ebp+var_29], 39h ; '9' ; jumptable 0800005A case 76
.text:080000AE EB 53 jmp short def_800005A ; jumptable 0800005A default case
.text:080000AE
.text:080000B0 ; ---------------------------------------------------------------------------
.text:080000B0
.text:080000B0 loc_80000B0: ; CODE XREF: do_phase+5A↑j
.text:080000B0 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000B0 C6 45 D7 6F mov [ebp+var_29], 6Fh ; 'o' ; jumptable 0800005A case 77
.text:080000B4 EB 4D jmp short def_800005A ; jumptable 0800005A default case
.text:080000B4
.text:080000B6 ; ---------------------------------------------------------------------------
.text:080000B6
.text:080000B6 loc_80000B6: ; CODE XREF: do_phase+5A↑j
.text:080000B6 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000B6 C6 45 D7 59 mov [ebp+var_29], 59h ; 'Y' ; jumptable 0800005A case 78
.text:080000BA EB 47 jmp short def_800005A ; jumptable 0800005A default case
.text:080000BA
.text:080000BC ; ---------------------------------------------------------------------------
.text:080000BC
.text:080000BC loc_80000BC: ; CODE XREF: do_phase+5A↑j
.text:080000BC ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000BC C6 45 D7 45 mov [ebp+var_29], 45h ; 'E' ; jumptable 0800005A case 79
.text:080000C0 EB 41 jmp short def_800005A ; jumptable 0800005A default case
.text:080000C0
.text:080000C2 ; ---------------------------------------------------------------------------
.text:080000C2
.text:080000C2 loc_80000C2: ; CODE XREF: do_phase+5A↑j
.text:080000C2 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000C2 C6 45 D7 3F mov [ebp+var_29], 3Fh ; '?' ; jumptable 0800005A case 80
.text:080000C6 EB 3B jmp short def_800005A ; jumptable 0800005A default case
.text:080000C6
.text:080000C8 ; ---------------------------------------------------------------------------
.text:080000C8
.text:080000C8 loc_80000C8: ; CODE XREF: do_phase+5A↑j
.text:080000C8 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000C8 C6 45 D7 67 mov [ebp+var_29], 67h ; 'g' ; jumptable 0800005A case 81
.text:080000CC EB 35 jmp short def_800005A ; jumptable 0800005A default case
.text:080000CC
.text:080000CE ; ---------------------------------------------------------------------------
.text:080000CE
.text:080000CE loc_80000CE: ; CODE XREF: do_phase+5A↑j
.text:080000CE ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000CE C6 45 D7 30 mov [ebp+var_29], 30h ; '0' ; jumptable 0800005A case 82
.text:080000D2 EB 2F jmp short def_800005A ; jumptable 0800005A default case
.text:080000D2
.text:080000D4 ; ---------------------------------------------------------------------------
.text:080000D4
.text:080000D4 loc_80000D4: ; CODE XREF: do_phase+5A↑j
.text:080000D4 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000D4 C6 45 D7 54 mov [ebp+var_29], 54h ; 'T' ; jumptable 0800005A case 83
.text:080000D8 EB 29 jmp short def_800005A ; jumptable 0800005A default case
.text:080000D8
.text:080000DA ; ---------------------------------------------------------------------------
.text:080000DA
.text:080000DA loc_80000DA: ; CODE XREF: do_phase+5A↑j
.text:080000DA ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000DA C6 45 D7 7E mov [ebp+var_29], 7Eh ; '~' ; jumptable 0800005A case 84
.text:080000DE EB 23 jmp short def_800005A ; jumptable 0800005A default case
.text:080000DE
.text:080000E0 ; ---------------------------------------------------------------------------
.text:080000E0
.text:080000E0 loc_80000E0: ; CODE XREF: do_phase+5A↑j
.text:080000E0 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000E0 C6 45 D7 3C mov [ebp+var_29], 3Ch ; '<' ; jumptable 0800005A case 85
.text:080000E4 EB 1D jmp short def_800005A ; jumptable 0800005A default case
.text:080000E4
.text:080000E6 ; ---------------------------------------------------------------------------
.text:080000E6
.text:080000E6 loc_80000E6: ; CODE XREF: do_phase+5A↑j
.text:080000E6 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000E6 C6 45 D7 41 mov [ebp+var_29], 41h ; 'A' ; jumptable 0800005A case 86
.text:080000EA EB 17 jmp short def_800005A ; jumptable 0800005A default case
.text:080000EA
.text:080000EC ; ---------------------------------------------------------------------------
.text:080000EC
.text:080000EC loc_80000EC: ; CODE XREF: do_phase+5A↑j
.text:080000EC ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000EC C6 45 D7 7B mov [ebp+var_29], 7Bh ; '{' ; jumptable 0800005A case 87
.text:080000F0 EB 11 jmp short def_800005A ; jumptable 0800005A default case
.text:080000F0
.text:080000F2 ; ---------------------------------------------------------------------------
.text:080000F2
.text:080000F2 loc_80000F2: ; CODE XREF: do_phase+5A↑j
.text:080000F2 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000F2 C6 45 D7 5A mov [ebp+var_29], 5Ah ; 'Z' ; jumptable 0800005A case 88
.text:080000F6 EB 0B jmp short def_800005A ; jumptable 0800005A default case
.text:080000F6
.text:080000F8 ; ---------------------------------------------------------------------------
.text:080000F8
.text:080000F8 loc_80000F8: ; CODE XREF: do_phase+5A↑j
.text:080000F8 ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000F8 C6 45 D7 32 mov [ebp+var_29], 32h ; '2' ; jumptable 0800005A case 89
.text:080000FC EB 05 jmp short def_800005A ; jumptable 0800005A default case
.text:080000FC
.text:080000FE ; ---------------------------------------------------------------------------
.text:080000FE
.text:080000FE loc_80000FE: ; CODE XREF: do_phase+5A↑j
.text:080000FE ; DATA XREF: .rodata:jpt_800005A↓o
.text:080000FE C6 45 D7 44 mov [ebp+var_29], 44h ; 'D' ; jumptable 0800005A case 90
.text:08000102 90 nop
phase5.o
/*需要填充的.rel.text和.rel.rodata段的可读表示形式*/
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000009 R_386_32 EFRspd
00000018 R_386_32 .rodata
00000029 R_386_32 EFRspd
0000003d R_386_32 EFRspd
0000004e R_386_32 EFRspd
00000060 R_386_32 EFRspd
00000000 R_386_NONE *ABS*
0000008b R_386_32 CODE
00000000 R_386_NONE *ABS*
000000a7 R_386_PC32 transform_code
000000af R_386_32 CODE
000000cf R_386_PC32 strlen
00000000 R_386_NONE *ABS*
00000102 R_386_32 CODE
00000000 R_386_NONE *ABS*
0000015e R_386_32 BUF
00000000 R_386_NONE *ABS*
00000000 R_386_NONE *ABS*
00000173 R_386_PC32 puts
0000017b R_386_32 notify
00000188 R_386_32 BUF
0000018f R_386_PC32 client
RELOCATION RECORDS FOR [.rodata]:
OFFSET TYPE VALUE
000000c0 R_386_32 .text
00000000 R_386_NONE *ABS*
000000c8 R_386_32 .text
000000cc R_386_32 .text
00000000 R_386_NONE *ABS*
000000d4 R_386_32 .text
000000d8 R_386_32 .text
00000000 R_386_NONE *ABS*
/*.rel.text段的十六进制输出*/
0x00000000 09000000 01090000 18000000 01050000 ................
0x00000010 29000000 01090000 3d000000 01090000 ).......=.......
0x00000020 4e000000 01090000 60000000 01090000 N.......`.......
0x00000030 00000000 00000000 8b000000 010c0000 ................
0x00000040 00000000 00000000 a7000000 020d0000 ................
0x00000050 af000000 010c0000 cf000000 02100000 ................
0x00000060 00000000 00000000 02010000 010c0000 ................
0x00000070 00000000 00000000 5e010000 010b0000 ........^.......
0x00000080 00000000 00000000 00000000 00000000 ................
0x00000090 73010000 02120000 7b010000 01130000 s.......{.......
0x000000a0 88010000 010b0000 8f010000 02140000 ................
/*符号表*/
Symbol table '.symtab' contains 22 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS phase5.c
2: 00000000 0 SECTION LOCAL DEFAULT 1 .text
3: 00000000 0 SECTION LOCAL DEFAULT 3 .data
4: 00000000 0 SECTION LOCAL DEFAULT 5 .bss
5: 00000000 0 SECTION LOCAL DEFAULT 6 .rodata
6: 00000000 0 SECTION LOCAL DEFAULT 9 .note.GNU-stack
7: 00000000 0 SECTION LOCAL DEFAULT 10 .eh_frame
8: 00000000 0 SECTION LOCAL DEFAULT 8 .comment
9: 00000000 44 OBJECT GLOBAL DEFAULT 6 EFRspd
10: 00000040 128 OBJECT GLOBAL DEFAULT 6 PtPNnD
11: 00000000 11 OBJECT GLOBAL DEFAULT 3 BUF
12: 0000000b 1 OBJECT GLOBAL DEFAULT 3 CODE
13: 00000000 129 FUNC GLOBAL DEFAULT 1 transform_code
14: 00000081 65 FUNC GLOBAL DEFAULT 1 generate_code
15: 000000c2 133 FUNC GLOBAL DEFAULT 1 encode
16: 00000000 0 NOTYPE GLOBAL DEFAULT UND strlen
17: 00000147 82 FUNC GLOBAL DEFAULT 1 do_phase
18: 00000000 0 NOTYPE GLOBAL DEFAULT UND puts
19: 00000000 0 NOTYPE GLOBAL DEFAULT UND notify
20: 00000000 0 NOTYPE GLOBAL DEFAULT UND client
21: 0000000c 4 OBJECT GLOBAL DEFAULT 3 phase
在解答这道题目时,我首先通过向AI咨询,初步了解了包括符号表、.bss段、.rodata段、.rel.text段等一系列与实验相关但我并不熟悉的概念。随后,我运用了gcc、readelf和objdump等工具获取了phase5.o文件的关键信息,包括符号表内容、文件.text段的反汇编代码、重定位节的可读表示形式及其对应的十六进制数据,并将这些重要数据保存到文件中以备后续参考。
接下来,我依据重定位节中的“OFFSET”字段所提供的线索,大致圈定了待填充空位对应的代码区域。然后,我通过对相应text段内的汇编代码进行解读,最终确定了需要执行重定位操作的具体指令,它的相对偏移地址以及关联到的符号。使用IDA工具查看相应的汇编语言代码和伪代码会起到积极作用,因为如果重定位失败导致逻辑混乱,IDA会自动标识出相关的指令,有助于更准确地定位问题所在。
又因为考虑到进行修改需要直接输入十六进制数,所以我们应该先观察并分析重定位节中已知的十六进制数据,并结合重定位节的可读表示形式和符号表信息,通过逻辑从相对偏移地址和关联到的符号推导出应当填入当前空位的十六进制数。最后使用010 Editor打开phase5. o文件,借助其查找功能定位到待修改的内存区域,往空位中填充正确的十六进制数即可。
当然,对空位的填充并非是一次性完成的。每次填充完一个空位,我都会使用IDA观察相应的伪代码是否符合逻辑预期,以此判断修改是否正确。在确认无误后,我才会开始下一个空位的填充工作。就这样通过不断地尝试、验证和调整,我最终才完成了实验。
/*使用IDA查看修改前的.rodata段*/
.rodata:08000280 1E 00 00 08 jpt_800001C dd offset loc_800001E ; DATA XREF: transform_code+15↑r
.rodata:08000280 ; jump table for switch statement
.rodata:08000284 23 db 23h ; #
.rodata:08000285 00 db 0
.rodata:08000286 00 db 0
.rodata:08000287 00 db 0
.rodata:08000288 78 00 00 08 dd offset def_800001C ; jumptable 0800001C default case
.rodata:0800028C 37 00 00 08 dd offset loc_8000037
.rodata:08000290 48 db 48h ; H
.rodata:08000291 00 db 0
.rodata:08000292 00 db 0
.rodata:08000293 00 db 0
.rodata:08000294 5A 00 00 08 dd offset loc_800005A
.rodata:08000298 78 00 00 08 dd offset def_800001C ; jumptable 0800001C default case
.rodata:0800029C 69 db 69h ; i
.rodata:0800029D 00 db 0
.rodata:0800029E 00 db 0
.rodata:0800029F 00 db 0
/*使用IDA查看修改后的.rodata段*/
.rodata:08000280 1E 00 00 08 23 00 00 08 78 00+jpt_800001C dd offset loc_800001E ; DATA XREF: transform_code+15↑r
.rodata:08000280 00 08 37 00 00 08 48 00 00 08+dd offset loc_8000023 ; jump table for switch statement
.rodata:08000280 5A 00 00 08 78 00 00 08 69 00+dd offset def_800001C
.rodata:08000280 00 08 dd offset loc_8000037
.rodata:08000280 dd offset loc_8000048
.rodata:08000280 dd offset loc_800005A
.rodata:08000280 dd offset def_800001C
.rodata:08000280 dd offset loc_8000069
首先,通过使用IDA对rel.rodata段中未填充的空位进行分析,我们可以合理推测这些位置需要进行重定位处理,其原因在于它们构成了switch语句的跳转表,即为一系列连续排列的地址。理论上,这些待重定位位置的偏移量应构成等差数列关系。此外,针对这些跳转表项的重定位类型和符号索引也应当保持一致,预计均为“R_386_32.text”。
然后是do_phase函数,有三处需要重定位。
/*使用IDA查看修改前的do_phase函数中需要重定位的部分
第一处: call near ptr loc_8000152+1
第二处:call near ptr loc_8000162+1
第三处:push 0*/
.text:0800014D 68 FF 00 00 00 push 0FFh
.text:08000152
.text:08000152 loc_8000152: ; CODE XREF: do_phase:loc_8000152↑p
.text:08000152 E8 FC FF FF FF call near ptr loc_8000152+1
.text:08000152
.text:08000152 do_phase endp ; sp-analysis failed
.text:08000152
.text:08000157 83 C4 04 add esp, 4
.text:0800015A 83 EC 0C sub esp, 0Ch
.text:0800015D 68 9C 01 00 08 push offset BUF ; "2023303157"
.text:08000162
.text:08000162 loc_8000162: ; CODE XREF: .text:loc_8000162↑p
.text:08000162 E8 FC FF FF FF call near ptr loc_8000162+1
.text:08000162
.text:08000167 83 C4 10 add esp, 10h
.text:0800016A 83 EC 0C sub esp, 0Ch
.text:0800016D 68 00 00 00 00 push 0
.text:08000172 E8 C5 01 00 00 call puts
原因:
用IDA分析伪代码可知函数“unsigned int __cdecl generate_code(char a1)”负责接收一个字符参数a1并生成一个新的编码;而函数“int __cdecl encode(char *s)”的作用是对输入的字符串s进行简单的字符编码。变量CODE 储存了0FFh,变量BUF储存了字符串‘学号’。那可以推测do_phase函数应该会先调用generate_code函数,修改CODE的值,再调用encode使用CODE编码BUF,接着调用puts函数输出编码后的结果,最后调用client函数上传结果到服务器。
再看encode函数,有一处需要重定位。
用IDA查看的需要修改的指令:
.text:080000F8 0F B6 88 00 00 00 00 movzx ecx, byte ptr [eax+0]
对应伪代码中的“s[i] = (*(_BYTE *)s[i] ^ CODE) & 0x7F;”
原因:
IDA智能地识别到了encode函数中缺失了一个数组变量,并在生成的伪代码中以符号's'来代表并标识这一缺失的数组,从而帮助我们更清晰地理解与分析函数逻辑。“s[i] = (*(_BYTE *)s[i] ^ CODE) & 0x7F;”是将s[i]处的字符先按字节解引用,然后与一个全局常量CODE进行异或(^)运算。然后对结果取低7位 (& 0x7F),确保结果是一个ASCII可打印字符的范围之内。在phase5.o文件中,我们发现了一个未被使用的char型数组变量PtPNnD[128],其内部储存了一系列符号。鉴于此情况,我们有充足的理由推测该数组可能在加密编码过程中扮演了关键的角色。
接着看generate_code函数,也是有一处需要重定位。
/*generate_code函数的伪代码*/
unsigned int __cdecl generate_code(char a1)
{
unsigned int result; // eax
unsigned int i; // [esp+Ch] [ebp-4h]
CODE = a1;
for ( i = 0; ; ++i )
{
result = i;
if ( i > 0xA )
break;
CODE = transform_code(MEMORY[0], i);
}
return result;
}
用IDA查看的需要修改的指令:
.text:08000098 0F B6 05 00 00 00 00 movzx eax, large byte ptr ds:0
对应伪代码中的“CODE = transform_code(MEMORY[0], i);”
原因:
IDA智能地识别到generate_code函数中缺失了一个变量,并在生成的伪代码中以符号'MEMORY[0]'来代表并标识这一缺失的变量,从而帮助我们更清晰地理解与分析函数逻辑。因为generate_code函数的伪代码中有“unsigned int __cdecl generate_code(char a1)”和“CODE = a1;”语句,所以写入了参数的CODE应该要有作为右值出现的机会,否则传入参数没有意义,那么待定的MEMORY[0]应该就是CODE。
最后看transform_code函数,仍然只有一处需要重定位。
/*这是transform_code函数的部分汇编代码,其中指令mov eax, ds:0[eax*4]需要重定位*/
.text:0800005A ; -----------------------------------------------------------
.text:0800005A
.text:0800005A loc_800005A: ; DATA XREF: .rodata:08000294↓o
.text:0800005A 8B 45 0C mov eax, [ebp+arg_4]
.text:0800005D 8B 04 85 C0 01 00 08 mov eax, ds:EFRspd[eax*4]
.text:08000064 31 45 08 xor [ebp+arg_0], eax
.text:08000067 EB 13 jmp short loc_800007C
.text:08000067
.text:08000069 ; ------------------------------------------------------------
.text:08000069 8B 45 0C mov eax, [ebp+arg_4]
.text:0800006C 8B 04 85 00 00 00 00 mov eax, ds:0[eax*4]
.text:08000073 89 45 08 mov [ebp+arg_0], eax
.text:08000076 EB 04 jmp short loc_800007C
.text:08000076
.text:08000078 ; ------------------------------------------------------------
transform_code函数内部采用了switch语句进行逻辑判断,不过之前已妥善处理了跳转表不完整的问题。
考虑到switch语句通常会涌现出多个相似的执行路径,我们可以合理推测这些分支中存在一定的共性。将.text:0800006C处的指令“8B 04 85 00 00 00 00 mov eax, ds:0[eax*4]”与其他分支中的指令“8B 04 85 C0 01 00 08 mov eax, ds:EFRspd[eax*4]”进行对比,不难发现它们属于同一类型的操作——都是基于eax值进行索引并从内存数组中加载数据到eax寄存器。然而,“8B 04 85 00 00 00 00”这条指令中的内存地址引用“ds:0[eax*4]”没有明确指定变量名EFRspd,这暗示了它可能是一个未完成重定位的相对地址引用。为了确保正确性,我们需要对这个地址进行适当的重定位,将它关联到正确的内存区域或变量名上。