CSAPP 二进制炸弹 binary bomb lab 3 第三关 ——深入理解计算机系统

337 阅读1分钟

CSAPP bomb lab3

Phase_3

0000000000400f43 <phase_3>:
// arg1=input (input是一个字符串)
  400f43:	48 83 ec 18          sub    $0x18,%rsp
  400f47:	48 8d 4c 24 0c       lea    0xc(%rsp),%rcx
  400f4c:	48 8d 54 24 08       lea    0x8(%rsp),%rdx
  400f51:	be cf 25 40 00       mov    $0x4025cf,%esi
  400f56:	b8 00 00 00 00       mov    $0x0,%eax
  400f5b:	e8 90 fc ff ff       callq  400bf0 <__isoc99_sscanf@plt>
  400f60:	83 f8 01             cmp    $0x1,%eax
  400f63:	7f 05                jg     400f6a <phase_3+0x27>
  400f65:	e8 d0 04 00 00       callq  40143a <explode_bomb>
  400f6a:	83 7c 24 08 07       cmpl   $0x7,0x8(%rsp)
  400f6f:	77 3c                ja     400fad <phase_3+0x6a>
  400f71:	8b 44 24 08          mov    0x8(%rsp),%eax
  400f75:	ff 24 c5 70 24 40 00 jmpq   *0x402470(,%rax,8)
  400f7c:	b8 cf 00 00 00       mov    $0xcf,%eax
  400f81:	eb 3b                jmp    400fbe <phase_3+0x7b>
  400f83:	b8 c3 02 00 00       mov    $0x2c3,%eax
  400f88:	eb 34                jmp    400fbe <phase_3+0x7b>
  400f8a:	b8 00 01 00 00       mov    $0x100,%eax
  400f8f:	eb 2d                jmp    400fbe <phase_3+0x7b>
  400f91:	b8 85 01 00 00       mov    $0x185,%eax
  400f96:	eb 26                jmp    400fbe <phase_3+0x7b>
  400f98:	b8 ce 00 00 00       mov    $0xce,%eax
  400f9d:	eb 1f                jmp    400fbe <phase_3+0x7b>
  400f9f:	b8 aa 02 00 00       mov    $0x2aa,%eax
  400fa4:	eb 18                jmp    400fbe <phase_3+0x7b>
  400fa6:	b8 47 01 00 00       mov    $0x147,%eax
  400fab:	eb 11                jmp    400fbe <phase_3+0x7b>
  400fad:	e8 88 04 00 00       callq  40143a <explode_bomb>
  400fb2:	b8 00 00 00 00       mov    $0x0,%eax
  400fb7:	eb 05                jmp    400fbe <phase_3+0x7b>
  400fb9:	b8 37 01 00 00       mov    $0x137,%eax
  400fbe:	3b 44 24 0c          cmp    0xc(%rsp),%eax
  400fc2:	74 05                je     400fc9 <phase_3+0x86>
  400fc4:	e8 71 04 00 00       callq  40143a <explode_bomb>
  400fc9:	48 83 c4 18          add    $0x18,%rsp
  400fcd:	c3                   retq   

phase_3中同样调用了sscanf,第二个参数rsi在调用前赋予了0x4025cf gdb中用 x/1s 0x4025cf查到是:“%d %d”,说明这个是输入两个int整数。image-20210705184932712然后写入第三、四参数,即rdx,rcx, rcx=rsp+0xcrdx=rsp+0x8, rdx和rcx其实是一个数组,令:rdx<=>&a[0],rcx<=>&a[1]

同样的套路,在调用Phase_3之前先要求按"%d %d"来将数据流写入到char *input, 然后调用sscanf(char *input,"%d %d",&a[0],&a[1])

若sscanf的返回值<=1,直接爆炸(说明先确保按正确的格式输入)。跳出sscanf后,if (a[0]<0 或 a[0]>7),也直接爆炸。(保证0 =< a[0] <=7)

后面有一个重要的命令:jmpq *0x402470(,%rax,8),由于rax=a[0],所以表明跳转到地址(0x402470+a[0]*8)中存放的地址(代码)。gdb下输入 x/8gx 0x402470得到: image-20210705184950365 这摆明是以rdx为索引的跳转表啊! 图中所写入的8个地址都在phase_3代码段中可查,switch的索引a[0]可以取0,1,2,3,4,5,6,7以及default,转成代码为:

void phase_3(char *input)
{
	int a[2];
	if ( sscanf(input,"%d %d",&a[0],&a[1]) != 2)
		bomb();
	switch (a[0]){
	case 0: goto 0x400f7c; break;
	case 1: goto 0x400fb9; break;
	case 2: goto 0x400f83; break;
	case 3: goto 0x400f8a; break;
	case 4: goto 0x400f91; break;
	case 5: goto 0x400f98; break;
	case 6: goto 0x400f9f; break;
	case 7: goto 0x400fa6; break;
	default:	bomb();
	}	
}

a[0]=0为例,真实的代码存放在0x402470对应的实际代码地址为400f7c:

  400f7c:	b8 cf 00 00 00       	mov    $0xcf,%eax
// eax=0xcf
  400fbe:	3b 44 24 0c          	cmp    0xc(%rsp),%eax			
  400fc2:	74 05                	je     400fc9 <phase_3+0x86>	
// if (eax==a[1])->成功! --> 所以a[1]=0xcf = 
  400fc4:	e8 71 04 00 00       	callq  40143a <explode_bomb>
  400fc9:	48 83 c4 18          	add    $0x18,%rsp	
// 同样的,可以令a[0]取另外7个数,也有对应的a[1]使得关卡通过。

因而,其中一个答案为:"0 207"