/*
* notrack
*/
这个指令在Intel手册上都查不到,网上也查不出个所以然,之前在逆向switch语句时见过,但没有深究。今再次遇到,一时也愣住了。通过调试,暂没看出有个什么特别之处,应该是gcc对switch优化的结果。
char ch = -1;
char *arg = "aAcC:GhH:nN:pglsStTuUVZ";
while ((ch = getopt_long(argc, argv, arg, var_option, NULL)) != -1) {
switch (ch) {
/*291a: 0f 84 fd 02 00 00 je 2c1d <__sprintf_chk@plt+0x4ad>
2920: 83 e8 41 sub $0x41,%eax // eax=eax-0x41, 转换成字符
2923: 83 f8 34 cmp $0x34,%eax // eax ?= 0x34 (52), 大小写字母共52个
2926: 0f 87 e9 00 00 00 ja 2a15 <__sprintf_chk@plt+0x2a5> */ // 大于52即不是有效字符跳转
// default:
/*292c: 48 63 04 83 movslq (%rbx,%rax,4),%rax // rbx=0x55555555ab78, (rbx)=0xffffbe9dffffbf2c, rax*4=0x20*4=0x80, rax=(0x55555555ab78+0x80)=0x55555555abf8:0xffffbe9dffffbdd4, rax=0xffffffffffffbdd4
2930: 48 01 d8 add %rbx,%rax // rax=0xffffffffffffbdd4+0x55555555ab78=0x55555555694c
2933: 3e ff e0 notrack jmpq *%rax */ // 0x55555555694c: 0x000100006b1205c7 --> x/i $rax => 0x55555555694c: movl $0x1,0x6b12(%rip)
/*2936: c7 05 20 6b 00 00 01 movl $0x1,0x6b20(%rip) # 9460 <stderr@@GLIBC_2.2.5+0x40>
293d: 00 00 00
2940: c7 05 82 69 00 00 00 movl $0x0,0x6982(%rip) # 92cc <_IO_stdin_used@@Base+0x32cc>
2947: 00 00 00
294a: eb b4 jmp 2900 <__sprintf_chk@plt+0x190> */
break;
case 'a':
/*294c: c7 05 12 6b 00 00 01 movl $0x1,0x6b12(%rip) # 9468 <stderr@@GLIBC_2.2.5+0x48>
2953: 00 00 00
2956: eb a8 jmp 2900 <__sprintf_chk@plt+0x190> */
gvar_9468 = 1;
break;
292c: 48 63 04 83 movslq (%rbx,%rax,4),%rax
2930: 48 01 d8 add %rbx,%rax
2933: 3e ff e0 notrack jmpq *%rax # rax=296c
2936: c7 05 20 6b 00 00 01 movl $0x1,0x6b20(%rip)
293d: 00 00 00
2940: c7 05 82 69 00 00 00 movl $0x0,0x6982(%rip)
2947: 00 00 00
294a: eb b4 jmp 2900 <__sprintf_chk@plt+0x190>
294c: c7 05 12 6b 00 00 01 movl $0x1,0x6b12(%rip)
2953: 00 00 00
2956: eb a8 jmp 2900 <__sprintf_chk@plt+0x190>
分析:
此处直接用PIE地址。
执行 notrack jmpq *%rax 时,经过上面的指令运算,rax里已经存放了要跳转的地址 296c 。没有 notrack 指令 jmp 指令也能跳转过去,自认为notrack指令无特别意义,仅作为 gcc 优化的结果。