CS:APP Bomb Lab
实验需求及分析
需求
“二进制炸弹”是作为目标代码文件提供给学生的程序。当运行时,它提示用户输入6个不同的字符串。如果其中任何一个不正确,炸弹就会“爆炸”。学生们必须通过拆卸和逆向工程程序来“拆除”他们自己独特的炸弹,以确定6个字符串应该是什么。
分析
实验提供一个可执行文件$bomb$,即要拆除的“二进制炸弹”,以及一份c语言代码$bomb.c$,$bomb.c$是炸弹的部分源代码($main$函数),通过$bomb.c$可知程序会读入六个字符串然后传入对应的$phase$函数中检验,若不正确就会爆炸,缺失的代码正是这些$phase$函数,故我们要通过反汇编来看$phase$函数做了什么进而确定要输入的字符串。
phase_1 (热身)
首先用$gdb$启动对$bomb$的调试,用$disass$指令对phase_1函数进行反汇编
gdb bomb
disass phase_1
可得如下结果
0x0000000000400ee0 <+0>: sub $0x8,%rsp
0x0000000000400ee4 <+4>: mov $0x402400,%esi
0x0000000000400ee9 <+9>: callq 0x401338 <strings_not_equal>
0x0000000000400eee <+14>: test %eax,%eax
0x0000000000400ef0 <+16>: je 0x400ef7 <phase_1+23>
0x0000000000400ef2 <+18>: callq 0x40143a <explode_bomb>
0x0000000000400ef7 <+23>: add $0x8,%rsp
0x0000000000400efb <+27>: retq
- +0: 开辟栈帧。
- +4 ~ +9: 将立即数$0x402400$存入第二参数寄存器$rsi$中,调用函数”strings_not_equal”。
- [rsi]中字符串与读入字符串进行对比,相等返回0,不等返回1。
- +14 ~ +18: 对返回值进行判断,若等于0则跳过引爆函数”explode_bomb”,否则引爆炸弹。
- +23 ~ +27: 回收栈空间,返回。
综上,只要输入的字符串与首地址为$0x402400$的字符串相等即可。
可使用$x/s$指令输出地址$0x402400$处存储的字符串。
x/s 0x402400
得到phase_1答案
0x402400: "Border relations with Canada have never been better."
phase_2 (数组)
第一步为反汇编该函数,可得如下结果
0x0000000000400efc <+0>: push %rbp
0x0000000000400efd <+1>: push %rbx
0x0000000000400efe <+2>: sub $0x28,%rsp
0x0000000000400f02 <+6>: mov %rsp,%rsi
0x0000000000400f05 <+9>: callq 0x40145c <read_six_numbers>
0x0000000000400f0a <+14>: cmpl $0x1,(%rsp)
0x0000000000400f0e <+18>: je 0x400f30 <phase_2+52>
0x0000000000400f10 <+20>: callq 0x40143a <explode_bomb>
0x0000000000400f15 <+25>: jmp 0x400f30 <phase_2+52>
0x0000000000400f17 <+27>: mov -0x4(%rbx),%eax
0x0000000000400f1a <+30>: add %eax,%eax
0x0000000000400f1c <+32>: cmp %eax,(%rbx)
0x0000000000400f1e <+34>: je 0x400f25 <phase_2+41>
0x0000000000400f20 <+36>: callq 0x40143a <explode_bomb>
0x0000000000400f25 <+41>: add $0x4,%rbx
0x0000000000400f29 <+45>: cmp %rbp,%rbx
0x0000000000400f2c <+48>: jne 0x400f17 <phase_2+27>
0x0000000000400f2e <+50>: jmp 0x400f3c <phase_2+64>
0x0000000000400f30 <+52>: lea 0x4(%rsp),%rbx
0x0000000000400f35 <+57>: lea 0x18(%rsp),%rbp
0x0000000000400f3a <+62>: jmp 0x400f17 <phase_2+27>
0x0000000000400f3c <+64>: add $0x28,%rsp
0x0000000000400f40 <+68>: pop %rbx
0x0000000000400f41 <+69>: pop %rbp
0x0000000000400f42 <+70>: retq
- +0 ~ +2: 保存寄存器$rbx$、$rbp$状态,开辟栈帧。
- +6 ~ +9: 将栈顶指针作为参数传入函数”read_six_numbers”中。
- 该函数从读入的字符串中读取6个整数存入栈空间[rsp] ~ [rsp+20]。
- +14 ~ +20: 判断[rsp]存储的值是否等于1,不等则引爆炸弹,由此可知第一个数为1。
- +27 ~ +62: 利用寄存器$rbx$、$rbp$、$rax$取出栈中元素进行对比,要求为后一个数是前一个数的两倍。
- +64 ~ +70: 回收栈空间,还原寄存器$rbx$、$rbp$状态,返回。
综上可得答案为
1 2 4 8 16 32
phase_3 (switch)
第一步为反汇编该函数,可得如下结果
0x0000000000400f43 <+0>: sub $0x18,%rsp
0x0000000000400f47 <+4>: lea 0xc(%rsp),%rcx
0x0000000000400f4c <+9>: lea 0x8(%rsp),%rdx
0x0000000000400f51 <+14>: mov $0x4025cf,%esi
0x0000000000400f56 <+19>: mov $0x0,%eax
0x0000000000400f5b <+24>: callq 0x400bf0 <__isoc99_sscanf@plt>
0x0000000000400f60 <+29>: cmp $0x1,%eax
0x0000000000400f63 <+32>: jg 0x400f6a <phase_3+39>
0x0000000000400f65 <+34>: callq 0x40143a <explode_bomb>
0x0000000000400f6a <+39>: cmpl $0x7,0x8(%rsp)
0x0000000000400f6f <+44>: ja 0x400fad <phase_3+106>
0x0000000000400f71 <+46>: mov 0x8(%rsp),%eax
0x0000000000400f75 <+50>: jmpq *0x402470(,%rax,8)
0x0000000000400f7c <+57>: mov $0xcf,%eax
0x0000000000400f81 <+62>: jmp 0x400fbe <phase_3+123>
0x0000000000400f83 <+64>: mov $0x2c3,%eax
0x0000000000400f88 <+69>: jmp 0x400fbe <phase_3+123>
0x0000000000400f8a <+71>: mov $0x100,%eax
0x0000000000400f8f <+76>: jmp 0x400fbe <phase_3+123>
0x0000000000400f91 <+78>: mov $0x185,%eax
0x0000000000400f96 <+83>: jmp 0x400fbe <phase_3+123>
0x0000000000400f98 <+85>: mov $0xce,%eax
0x0000000000400f9d <+90>: jmp 0x400fbe <phase_3+123>
0x0000000000400f9f <+92>: mov $0x2aa,%eax
0x0000000000400fa4 <+97>: jmp 0x400fbe <phase_3+123>
0x0000000000400fa6 <+99>: mov $0x147,%eax
0x0000000000400fab <+104>: jmp 0x400fbe <phase_3+123>
0x0000000000400fad <+106>: callq 0x40143a <explode_bomb>
0x0000000000400fb2 <+111>: mov $0x0,%eax
0x0000000000400fb7 <+116>: jmp 0x400fbe <phase_3+123>
0x0000000000400fb9 <+118>: mov $0x137,%eax
0x0000000000400fbe <+123>: cmp 0xc(%rsp),%eax
0x0000000000400fc2 <+127>: je 0x400fc9 <phase_3+134>
0x0000000000400fc4 <+129>: callq 0x40143a <explode_bomb>
0x0000000000400fc9 <+134>: add $0x18,%rsp
0x0000000000400fcd <+138>: retq
- +0: 开辟栈帧。
- +4 ~ +24: 从读入的字符串中取出两个整数存入栈空间[rsp+8] ~ [rsp+12]。
- +29 ~ +34: 通过返回值判断是否成功从字符串读入两个整数,若读入的个数小于2则引爆炸弹。
- +39 ~ +44: 判断第一个整数是否大于7,若大于则引爆炸弹。
- +46 ~ +118: 根据第一个整数进行跳转,跳转后将一个立即数存入$rax$。
- 可用
x/a
指令来观察跳转的目的地址,进而可知存入的立即数是什么。
- 可用
- +123 ~ +129: 判断第二个整数与寄存器$rax$中的立即数是否相等,若不等则引爆炸弹。
- +134 ~ +138: 回收栈空间,返回。
我们可令第一个数为0,此时跳转的目标地址为[0x402470],x/a 0x402470
查看得
0x402470: 0x400f7c <phase_3+57>
又汇编代码可知此时存入的立即数为$0xcf$,综上可知答案为
0 207
phase_4 (递归)
第一步为反汇编该函数,可得如下结果
0x000000000040100c <+0>: sub $0x18,%rsp
0x0000000000401010 <+4>: lea 0xc(%rsp),%rcx
0x0000000000401015 <+9>: lea 0x8(%rsp),%rdx
0x000000000040101a <+14>: mov $0x4025cf,%esi
0x000000000040101f <+19>: mov $0x0,%eax
0x0000000000401024 <+24>: callq 0x400bf0 <__isoc99_sscanf@plt>
0x0000000000401029 <+29>: cmp $0x2,%eax
0x000000000040102c <+32>: jne 0x401035 <phase_4+41>
0x000000000040102e <+34>: cmpl $0xe,0x8(%rsp)
0x0000000000401033 <+39>: jbe 0x40103a <phase_4+46>
0x0000000000401035 <+41>: callq 0x40143a <explode_bomb>
0x000000000040103a <+46>: mov $0xe,%edx
0x000000000040103f <+51>: mov $0x0,%esi
0x0000000000401044 <+56>: mov 0x8(%rsp),%edi
0x0000000000401048 <+60>: callq 0x400fce <func4>
0x000000000040104d <+65>: test %eax,%eax
0x000000000040104f <+67>: jne 0x401058 <phase_4+76>
0x0000000000401051 <+69>: cmpl $0x0,0xc(%rsp)
0x0000000000401056 <+74>: je 0x40105d <phase_4+81>
0x0000000000401058 <+76>: callq 0x40143a <explode_bomb>
0x000000000040105d <+81>: add $0x18,%rsp
0x0000000000401061 <+85>: retq
- +0: 开辟栈帧。
- +4 ~ +24: 从读入的字符串中取出两个整数存入栈空间[rsp+8] ~ [rsp+12]。
- +29 ~ +32: 通过返回值判断是否成功从字符串读入两个整数,若读入的个数不等于2则引爆炸弹。
- +34 ~ +39: 判断第一个整数是否大于14,若大于14则引爆炸弹。
- +46 ~ +60: 调用函数”func4”
- 参数寄存器: $rdi$ = [rsp+8],$rsi$ = 0,$rdx$ = 14。
- +65 ~ +67: 判断返回值是否等于0,若不等于0则引爆炸弹。
- +69 ~ +76: 判断第二个整数是否等于0,若不等则引爆炸弹。
- +81 ~ +85: 回收栈空间,返回。
通过以上分析可知,我们需要调整第一个整数使得函数”func4”返回0。
func4
反汇编该函数,看看里面有什么
起始时有: $rdi$ = 第一个整数,$rsi$ = 0,$rdx$ = 14。
0x0000000000400fce <+0>: sub $0x8,%rsp
0x0000000000400fd2 <+4>: mov %edx,%eax
0x0000000000400fd4 <+6>: sub %esi,%eax
0x0000000000400fd6 <+8>: mov %eax,%ecx
0x0000000000400fd8 <+10>: shr $0x1f,%ecx
0x0000000000400fdb <+13>: add %ecx,%eax
0x0000000000400fdd <+15>: sar %eax
0x0000000000400fdf <+17>: lea (%rax,%rsi,1),%ecx
0x0000000000400fe2 <+20>: cmp %edi,%ecx
0x0000000000400fe4 <+22>: jle 0x400ff2 <func4+36>
0x0000000000400fe6 <+24>: lea -0x1(%rcx),%edx
0x0000000000400fe9 <+27>: callq 0x400fce <func4>
0x0000000000400fee <+32>: add %eax,%eax
0x0000000000400ff0 <+34>: jmp 0x401007 <func4+57>
0x0000000000400ff2 <+36>: mov $0x0,%eax
0x0000000000400ff7 <+41>: cmp %edi,%ecx
0x0000000000400ff9 <+43>: jge 0x401007 <func4+57>
0x0000000000400ffb <+45>: lea 0x1(%rcx),%esi
0x0000000000400ffe <+48>: callq 0x400fce <func4>
0x0000000000401003 <+53>: lea 0x1(%rax,%rax,1),%eax
0x0000000000401007 <+57>: add $0x8,%rsp
0x000000000040100b <+61>: retq
其对应c代码大体如下
//起始:rdi = 第一个整数,rsi = 0,rdx = 14。
int func4 (int rdi,int rsi,int rdx){
int rax = rdx - rsi;
rax = (rax + rax最高位) >> 1;
int rcx = rax + rsi;
if(rcx > rdi)
return func4(rdi,rsi,rcx-1) * 2;
else if(rcx < rdi)
return func4(rdi,rsi,rcx+1) * 2 + 1;
else return 0;
}
结合$rdx$、$rsi$初值易知当第一个整数为7时,函数会直接返回0。
综上答案为:
7 0
phase_5 (字符串)
第一步为反汇编该函数,可得如下结果
0x0000000000401062 <+0>: push %rbx
0x0000000000401063 <+1>: sub $0x20,%rsp
0x0000000000401067 <+5>: mov %rdi,%rbx
0x000000000040106a <+8>: mov %fs:0x28,%rax
0x0000000000401073 <+17>: mov %rax,0x18(%rsp)
0x0000000000401078 <+22>: xor %eax,%eax
0x000000000040107a <+24>: callq 0x40131b <string_length>
0x000000000040107f <+29>: cmp $0x6,%eax
0x0000000000401082 <+32>: je 0x4010d2 <phase_5+112>
0x0000000000401084 <+34>: callq 0x40143a <explode_bomb>
0x0000000000401089 <+39>: jmp 0x4010d2 <phase_5+112>
0x000000000040108b <+41>: movzbl (%rbx,%rax,1),%ecx
0x000000000040108f <+45>: mov %cl,(%rsp)
0x0000000000401092 <+48>: mov (%rsp),%rdx
0x0000000000401096 <+52>: and $0xf,%edx
0x0000000000401099 <+55>: movzbl 0x4024b0(%rdx),%edx
0x00000000004010a0 <+62>: mov %dl,0x10(%rsp,%rax,1)
0x00000000004010a4 <+66>: add $0x1,%rax
0x00000000004010a8 <+70>: cmp $0x6,%rax
0x00000000004010ac <+74>: jne 0x40108b <phase_5+41>
0x00000000004010ae <+76>: movb $0x0,0x16(%rsp)
0x00000000004010b3 <+81>: mov $0x40245e,%esi
0x00000000004010b8 <+86>: lea 0x10(%rsp),%rdi
0x00000000004010bd <+91>: callq 0x401338 <strings_not_equal>
0x00000000004010c2 <+96>: test %eax,%eax
0x00000000004010c4 <+98>: je 0x4010d9 <phase_5+119>
0x00000000004010c6 <+100>: callq 0x40143a <explode_bomb>
0x00000000004010cb <+105>: nopl 0x0(%rax,%rax,1)
0x00000000004010d0 <+110>: jmp 0x4010d9 <phase_5+119>
0x00000000004010d2 <+112>: mov $0x0,%eax
0x00000000004010d7 <+117>: jmp 0x40108b <phase_5+41>
0x00000000004010d9 <+119>: mov 0x18(%rsp),%rax
0x00000000004010de <+124>: xor %fs:0x28,%rax
0x00000000004010e7 <+133>: je 0x4010ee <phase_5+140>
0x00000000004010e9 <+135>: callq 0x400b30 <__stack_chk_fail@plt>
0x00000000004010ee <+140>: add $0x20,%rsp
0x00000000004010f2 <+144>: pop %rbx
0x00000000004010f3 <+145>: retq
- +0 ~ +1: 保存寄存器$rbx$状态,开辟栈帧。
- +8 ~ +17: 将金丝雀值放入栈中,提供栈保护者机制。
- +22 ~ +34: 判断读入的字符串长度是否为6,若不为6则引爆炸弹。
- +41 ~ +110:
- +41 ~ +74:用读入数据的低4位作为数组下标,从首地址为$0x4024b0$的字符串中取出子序列,并将子序列存入[rsp+16] ~ [rsp+21]。
- +76 ~ +110:将取出的字符串子序列与首地址为$0x40245e$的字符串进行比较,若不相等则引爆炸弹。
- +119 ~ +135: 检查金丝雀值是否被修改,若被修改则说明发生了缓冲区溢出,会导致程序异常退出。
- +140 ~ +145: 回收栈空间,还原寄存器$rbx$状态,返回。
通过x/s
指令可查看首地址为$0x4024b0$、$0x40245e$的字符串
0x4024b0 <array.3449>: "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"
0x40245e: "flyers"
要从字符串[0x4024b0]中取出字符串[0x40245e]则需要获取下标序列为$9,15,14,5,6,7$;
即只要输入的字符串的第4位对应的10进制数位$9,15,14,5,6,7$即可。
综上,可得答案为:
)/.%&'
phase_6 (单链表)
第一步为反汇编该函数,可得如下结果
0x00000000004010f4 <+0>: push %r14
0x00000000004010f6 <+2>: push %r13
0x00000000004010f8 <+4>: push %r12
0x00000000004010fa <+6>: push %rbp
0x00000000004010fb <+7>: push %rbx
0x00000000004010fc <+8>: sub $0x50,%rsp
0x0000000000401100 <+12>: mov %rsp,%r13
0x0000000000401103 <+15>: mov %rsp,%rsi
0x0000000000401106 <+18>: callq 0x40145c <read_six_numbers>
0x000000000040110b <+23>: mov %rsp,%r14
0x000000000040110e <+26>: mov $0x0,%r12d
0x0000000000401114 <+32>: mov %r13,%rbp
0x0000000000401117 <+35>: mov 0x0(%r13),%eax
0x000000000040111b <+39>: sub $0x1,%eax
0x000000000040111e <+42>: cmp $0x5,%eax
0x0000000000401121 <+45>: jbe 0x401128 <phase_6+52>
0x0000000000401123 <+47>: callq 0x40143a <explode_bomb>
0x0000000000401128 <+52>: add $0x1,%r12d
0x000000000040112c <+56>: cmp $0x6,%r12d
0x0000000000401130 <+60>: je 0x401153 <phase_6+95>
0x0000000000401132 <+62>: mov %r12d,%ebx
0x0000000000401135 <+65>: movslq %ebx,%rax
0x0000000000401138 <+68>: mov (%rsp,%rax,4),%eax
0x000000000040113b <+71>: cmp %eax,0x0(%rbp)
0x000000000040113e <+74>: jne 0x401145 <phase_6+81>
0x0000000000401140 <+76>: callq 0x40143a <explode_bomb>
0x0000000000401145 <+81>: add $0x1,%ebx
0x0000000000401148 <+84>: cmp $0x5,%ebx
0x000000000040114b <+87>: jle 0x401135 <phase_6+65>
0x000000000040114d <+89>: add $0x4,%r13
0x0000000000401151 <+93>: jmp 0x401114 <phase_6+32>
0x0000000000401153 <+95>: lea 0x18(%rsp),%rsi
0x0000000000401158 <+100>: mov %r14,%rax
0x000000000040115b <+103>: mov $0x7,%ecx
0x0000000000401160 <+108>: mov %ecx,%edx
0x0000000000401162 <+110>: sub (%rax),%edx
0x0000000000401164 <+112>: mov %edx,(%rax)
0x0000000000401166 <+114>: add $0x4,%rax
0x000000000040116a <+118>: cmp %rsi,%rax
0x000000000040116d <+121>: jne 0x401160 <phase_6+108>
0x000000000040116f <+123>: mov $0x0,%esi
0x0000000000401174 <+128>: jmp 0x401197 <phase_6+163>
0x0000000000401176 <+130>: mov 0x8(%rdx),%rdx
0x000000000040117a <+134>: add $0x1,%eax
0x000000000040117d <+137>: cmp %ecx,%eax
0x000000000040117f <+139>: jne 0x401176 <phase_6+130>
0x0000000000401181 <+141>: jmp 0x401188 <phase_6+148>
0x0000000000401183 <+143>: mov $0x6032d0,%edx
0x0000000000401188 <+148>: mov %rdx,0x20(%rsp,%rsi,2)
0x000000000040118d <+153>: add $0x4,%rsi
0x0000000000401191 <+157>: cmp $0x18,%rsi
0x0000000000401195 <+161>: je 0x4011ab <phase_6+183>
0x0000000000401197 <+163>: mov (%rsp,%rsi,1),%ecx
0x000000000040119a <+166>: cmp $0x1,%ecx
0x000000000040119d <+169>: jle 0x401183 <phase_6+143>
0x000000000040119f <+171>: mov $0x1,%eax
0x00000000004011a4 <+176>: mov $0x6032d0,%edx
0x00000000004011a9 <+181>: jmp 0x401176 <phase_6+130>
0x00000000004011ab <+183>: mov 0x20(%rsp),%rbx
0x00000000004011b0 <+188>: lea 0x28(%rsp),%rax
0x00000000004011b5 <+193>: lea 0x50(%rsp),%rsi
0x00000000004011ba <+198>: mov %rbx,%rcx
0x00000000004011bd <+201>: mov (%rax),%rdx
0x00000000004011c0 <+204>: mov %rdx,0x8(%rcx)
0x00000000004011c4 <+208>: add $0x8,%rax
0x00000000004011c8 <+212>: cmp %rsi,%rax
0x00000000004011cb <+215>: je 0x4011d2 <phase_6+222>
0x00000000004011cd <+217>: mov %rdx,%rcx
0x00000000004011d0 <+220>: jmp 0x4011bd <phase_6+201>
0x00000000004011d2 <+222>: movq $0x0,0x8(%rdx)
0x00000000004011da <+230>: mov $0x5,%ebp
0x00000000004011df <+235>: mov 0x8(%rbx),%rax
0x00000000004011e3 <+239>: mov (%rax),%eax
0x00000000004011e5 <+241>: cmp %eax,(%rbx)
0x00000000004011e7 <+243>: jge 0x4011ee <phase_6+250>
0x00000000004011e9 <+245>: callq 0x40143a <explode_bomb>
0x00000000004011ee <+250>: mov 0x8(%rbx),%rbx
0x00000000004011f2 <+254>: sub $0x1,%ebp
0x00000000004011f5 <+257>: jne 0x4011df <phase_6+235>
0x00000000004011f7 <+259>: add $0x50,%rsp
0x00000000004011fb <+263>: pop %rbx
0x00000000004011fc <+264>: pop %rbp
0x00000000004011fd <+265>: pop %r12
0x00000000004011ff <+267>: pop %r13
0x0000000000401201 <+269>: pop %r14
0x0000000000401203 <+271>: retq
- +0 ~ +8: 将寄存器状态进行保存,开辟栈空间。
- +12 ~ +18: 将栈顶指针作为参数传入函数”read_six_numbers”中。
- 该函数从读入的字符串中读取6个整数存入栈空间[rsp] ~ [rsp+20]。
- +32 ~ +93: 外循环。(整体效果:对六个整数进行一定的判断)
- +35 ~ +47: 判断当前枚举到的数据是否在[1,6]之间。
- +53 ~ +60: 判断是否处理完六个数,若处理完则跳转到地址$0x401153$,结束循环。
- +65 ~ +87: 内循环
- 设当前枚举到第$i$个数据,内循环的作用是将其与第$i+1$ ~ 第$6$个数据进行对比,若有相同则引爆炸弹。
- +95 ~ +121: 用7减去[rsp] ~ [rsp+20]中的值,再将结果存回该段栈空间。
- +130 ~ +181: 外循环。(整体效果:将单链表中对应结点地址存入[rsp+32] ~ [rsp+72])
- +130 ~ +139: 内循环
- 用当前枚举到的整数寻找到单链表中对应节点,若整数值为x则寻找到的结点就是第x个结点。
- +148: 将单链表结点地址存入栈空间。
- +153 ~ +161: 判断是否使用完6个整数,若使用完则跳转到地址$0x4011ab$,结束循环。
- +130 ~ +139: 内循环
- +183 ~ +222: 单链表排序,以栈空间[rsp+32] ~ [rsp+72]存储的顺序为标准进行排序。
- +230 ~ +257: 要求重排后的单链表中,前一个结点存储的值的低32位大于后一个结点存储的值的低32位,否则引爆炸弹。
- +259 ~ +271: 回收栈空间,还原寄存器状态,返回。
用x/12a 0x6032d0
去查看单链表初始时存储的数据
0x6032d0 <node1>: 0x10000014c 0x6032e0 <node2>
0x6032e0 <node2>: 0x2000000a8 0x6032f0 <node3>
0x6032f0 <node3>: 0x30000039c 0x603300 <node4>
0x603300 <node4>: 0x4000002b3 0x603310 <node5>
0x603310 <node5>: 0x5000001dd 0x603320 <node6>
0x603320 <node6>: 0x6000001bb 0x0
由于要求重排后的单链表中前一个结点存储的值的低32位大于后一个结点存储的值的低32位。
可得重排后结点顺序为: $3、4、5、6、1、2$
由于处理后的整数值与重排后结点顺序一致(处理方式为用7减读入值)
可反推出答案为:
4 3 2 1 6 5