• CSAPP bomblab


    bomblab

    准备工作

    1. 首先我们将目标程序转换成汇编代码写入到bomb.txt方便查看
    2. 然后打开这个文件查看内容

    phase_1

    在这里插入图片描述
    这里我们直接转换成伪c代码:

    // 先将栈区减少8
    esi = 0x402400;
    strings_not_equal(rdi, rsi);
    if (eax != 0) {
    	explode_bomb();
    }
    return;
    // 恢复栈区
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    我们可以看到他把0x402400传入到一个strings_not_equal的函数了,那么里面肯定判断的是两个字符串是否相等,不相等就爆炸。所以我们输出0x402400位置的字符串即可。
    在这里插入图片描述
    第一题答案即为Border relations with Canada have never been better.
    在这里插入图片描述

    phase_2

    在这里插入图片描述
    这里我们直接转换成伪c代码:

    // stack init
    rsi = rbp;
    read_six_numbers();
    if (*rsp != 1) {
    	expoload_bomb();
    }
    rbx = rsp + 4;
    rbp = rsp + 20;
    400f17:
    eax = *(rbx - 4);
    eax = eax + eax;
    if (*rbx != eax) {
    	expload_bomb();
    }
    rbx += 4;
    if (rbx != rbp) {
    	jmp 400f17;
    }
    // stack init
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    首先我们在分析一下read_six_numbers():
    在这里插入图片描述我们发现esi中存的是0x4025c3,我们将这个内存地址指向的东西输出:
    在这里插入图片描述
    发现是六个数。
    然后我们分析phase_2:
    rbx是读入的第二个数,rbp是读入的最后一个数,首先我们判断读入的第一个数是否是1,如果不是爆炸,是的话我们比较后一项是否是前一项的两倍,如果不是也爆炸,所以最后我们得出的结果是:

    1. 一共六个数,读入的第一个数是1
    2. 每一个数是前面的数的两倍

    即答案为1 2 4 8 16 32
    在这里插入图片描述

    phase_3

    0000000000400f43 :
      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          call   400bf0 <__isoc99_sscanf@plt>
      400f60:       83 f8 01                cmp    $0x1,%eax
      400f63:       7f 05                   jg     400f6a 
      400f65:       e8 d0 04 00 00          call   40143a 
      400f6a:       83 7c 24 08 07          cmpl   $0x7,0x8(%rsp)
      400f6f:       77 3c                   ja     400fad 
      400f71:       8b 44 24 08             mov    0x8(%rsp),%eax
      400f75:       ff 24 c5 70 24 40 00    jmp    *0x402470(,%rax,8)
      400f7c:       b8 cf 00 00 00          mov    $0xcf,%eax
      400f81:       eb 3b                   jmp    400fbe 
      400f83:       b8 c3 02 00 00          mov    $0x2c3,%eax
      400f88:       eb 34                   jmp    400fbe 
      400f8a:       b8 00 01 00 00          mov    $0x100,%eax
      400f8f:       eb 2d                   jmp    400fbe 
      400f91:       b8 85 01 00 00          mov    $0x185,%eax
      400f96:       eb 26                   jmp    400fbe 
       400f98:       b8 ce 00 00 00          mov    $0xce,%eax
      400f9d:       eb 1f                   jmp    400fbe 
      400f9f:       b8 aa 02 00 00          mov    $0x2aa,%eax
      400fa4:       eb 18                   jmp    400fbe 
      400fa6:       b8 47 01 00 00          mov    $0x147,%eax
      400fab:       eb 11                   jmp    400fbe 
      400fad:       e8 88 04 00 00          call   40143a 
      400fb2:       b8 00 00 00 00          mov    $0x0,%eax
      400fb7:       eb 05                   jmp    400fbe 
      400fb9:       b8 37 01 00 00          mov    $0x137,%eax
      400fbe:       3b 44 24 0c             cmp    0xc(%rsp),%eax
      400fc2:       74 05                   je     400fc9 
      400fc4:       e8 71 04 00 00          call   40143a 
      400fc9:       48 83 c4 18             add    $0x18,%rsp
      400fcd:       c3                      ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    这里我们直接转换成伪c代码:

    // stack init
    rcx = rsp + 12;
    rdx = rsp + 8;
    esi = 0x4025cf; 
    eax = 0;
    __isoc99_sscanf@plt();
    if (eax <= 1) {
    	expload_bomb();
    }
    if (*(rsp + 8) > 7) {
    	jmp 400fad;
    }
    eax = *(rsp + 8);
    jmp *0x402470(, %rax, 8);
    switch {
    	case 0:
    		eax = 0xcf;
    		break;
    	case 2:
    		eax = 0x2c3;
    		break;
    	case 3:
    		eax = 0x100;
    		break;
    	case 4:
    		eax = 0x185;
    		break;
    	case 5:
    		eax = 0xce;
    		break;
    	case 6:
    		eax = 0x2aa;
    		break;
    	case 7:
    		eax = 0x147;
    		break;
    	case 1:
    		eax = 0x137;
    		break;
    }
    400fad:
    explode_bomb();
    eax = 0;
    if (eax != *(rsp + 12)) {
    	explode_bomb();
    }
    // stack init
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    首先我们看一下esi中指向的内容,发现我们需要输入的应该是两个整数
    在这里插入图片描述
    其次,根据

      400f75:       ff 24 c5 70 24 40 00    jmp    *0x402470(,%rax,8)
    
    • 1

    我们可以知道这里应该是switch case 语句,所以我们需要去找每个跳转语句的条件,我们输出出来一一对应
    在这里插入图片描述
    发现如果我们输入的第一个数和eax的关系:

    0  0xcf 
    1  0x137 
    2  0x2c3 
    3  0x100
    4  0x185 
    5  0xce
    6  0x2aa 
    7  0x147 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    所以我们要确保输入的第一个数和他得到的eax与输入的第二个数相同,即答案可以是

    0 207 
    1 311 
    2 707
    3 256 
    4 389 
    5 206 
    6 682 
    7 327
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    phase_4

    0000000000400fce :
      400fce:       48 83 ec 08             sub    $0x8,%rsp
      400fd2:       89 d0                   mov    %edx,%eax
      400fd4:       29 f0                   sub    %esi,%eax
      400fd6:       89 c1                   mov    %eax,%ecx
      400fd8:       c1 e9 1f                shr    $0x1f,%ecx
      400fdb:       01 c8                   add    %ecx,%eax
      400fdd:       d1 f8                   sar    %eax
      400fdf:       8d 0c 30                lea    (%rax,%rsi,1),%ecx
      400fe2:       39 f9                   cmp    %edi,%ecx
      400fe4:       7e 0c                   jle    400ff2 
      400fe6:       8d 51 ff                lea    -0x1(%rcx),%edx
      400fe9:       e8 e0 ff ff ff          call   400fce 
      400fee:       01 c0                   add    %eax,%eax
      400ff0:       eb 15                   jmp    401007 
      400ff2:       b8 00 00 00 00          mov    $0x0,%eax
      400ff7:       39 f9                   cmp    %edi,%ecx
      400ff9:       7d 0c                   jge    401007 
      400ffb:       8d 71 01                lea    0x1(%rcx),%esi
      400ffe:       e8 cb ff ff ff          call   400fce 
      401003:       8d 44 00 01             lea    0x1(%rax,%rax,1),%eax
      401007:       48 83 c4 08             add    $0x8,%rsp
      40100b:       c3                      ret
    
    000000000040100c :
      40100c:       48 83 ec 18             sub    $0x18,%rsp
      401010:       48 8d 4c 24 0c          lea    0xc(%rsp),%rcx
      401015:       48 8d 54 24 08          lea    0x8(%rsp),%rdx
      40101a:       be cf 25 40 00          mov    $0x4025cf,%esi
      40101f:       b8 00 00 00 00          mov    $0x0,%eax
      401024:       e8 c7 fb ff ff          call   400bf0 <__isoc99_sscanf@plt>
      401029:       83 f8 02                cmp    $0x2,%eax
      40102c:       75 07                   jne    401035 
      40102e:       83 7c 24 08 0e          cmpl   $0xe,0x8(%rsp)
      401033:       76 05                   jbe    40103a 
      401035:       e8 00 04 00 00          call   40143a 
      40103a:       ba 0e 00 00 00          mov    $0xe,%edx
      40103f:       be 00 00 00 00          mov    $0x0,%esi
      401044:       8b 7c 24 08             mov    0x8(%rsp),%edi
      401048:       e8 81 ff ff ff          call   400fce 
      40104d:       85 c0                   test   %eax,%eax
      40104f:       75 07                   jne    401058 
      401051:       83 7c 24 0c 00          cmpl   $0x0,0xc(%rsp)
      401056:       74 05                   je     40105d 
      401058:       e8 dd 03 00 00          call   40143a 
      40105d:       48 83 c4 18             add    $0x18,%rsp
      401061:       c3                      ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    这里我们直接转换成伪c代码:

    func4(rdi, rsi, rdx) {
    	// stack init
    	eax = edx;
    	eax -= esi;
    	eax = ecx;
    	ecx >>= 31;
    	eax += ecx;
    	eax >>= 1;
    	ecx = rax + rsi + 1;
    	if (ecx <= edi) {
    		jmp 400ff2;
    	}
    	edx = rcx - 1;
    	func4(rdi, rsi, rdx)
    	eax = eax + eax;
    	jmp 401007;
    	eax = 0;
    400ff2:
    	if (ecx >= edi) {
    		jmp 4010007;
    	}
    	esi = rcx + 1;
    	func4(rdi, rsi, rdx);
    	eax = eax + eax + 1;
    401007:
    	// stack init
    }
    
    phase_4(){
    	//stack init 
    	rcx = rsp + 12;
    	rdx = rsp + 8;
    	esi = 0x4025cf;
    	eax = 0;
    	__isoc99_sscanf@plt();
    	if (eax != 2) {
    		expload_bomb();
    	}
    	else if (*(rsp + 8) > 14) {
    		expload_bomb();
    	}
    	edx = 14;
    	esi = 0;
    	edi = *(rsp + 8);
    	func4(rdi, rsi, rdx);
    	if (eax != 0) {
    		expload_bomb();
    	}
    	else if (*(rsp + 12) != 0) {
    		expload_bomb();
    	}
    	// stack init
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    这里我们可以再化简下fun4()

    func4(int val, int l, int r) {
    	m = (r - l + (r - l) >> 31) >> 1; 
    	c = m + l;
    	if (c < val) {
    		return 2 * func4(val, l, m - 1) + 1;
    	} 
    	else if (c > val) {
    		return 2 * func4(val, l + 1, m);
    	}
    	else {
    		return 0;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    我们可以看出fun4其实就是二分查找,那么对于phase_4,我们需要查找的是我们输入的第一个数,查找的左右边界为0,14,最后我们要得到的结果是eax为0,那么我们可以知道,最后找到的时候返回值为0,所以往上几层每一层都要是往左走,所以得到的答案可以是

    7 0 
    3 0 
    1 0
    0 0
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    phase_5

    0000000000401062 :
      401062:       53                      push   %rbx
      401063:       48 83 ec 20             sub    $0x20,%rsp
      401067:       48 89 fb                mov    %rdi,%rbx
      40106a:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
      401071:       00 00
      401073:       48 89 44 24 18          mov    %rax,0x18(%rsp)
      401078:       31 c0                   xor    %eax,%eax
      40107a:       e8 9c 02 00 00          call   40131b 
      40107f:       83 f8 06                cmp    $0x6,%eax
      401082:       74 4e                   je     4010d2 
      401084:       e8 b1 03 00 00          call   40143a 
      401089:       eb 47                   jmp    4010d2 
      40108b:       0f b6 0c 03             movzbl (%rbx,%rax,1),%ecx
      40108f:       88 0c 24                mov    %cl,(%rsp)
      401092:       48 8b 14 24             mov    (%rsp),%rdx
      401096:       83 e2 0f                and    $0xf,%edx
      401099:       0f b6 92 b0 24 40 00    movzbl 0x4024b0(%rdx),%edx
      4010a0:       88 54 04 10             mov    %dl,0x10(%rsp,%rax,1)
      4010a4:       48 83 c0 01             add    $0x1,%rax
      4010a8:       48 83 f8 06             cmp    $0x6,%rax
      4010ac:       75 dd                   jne    40108b 
      4010ae:       c6 44 24 16 00          movb   $0x0,0x16(%rsp)
      4010b3:       be 5e 24 40 00          mov    $0x40245e,%esi
      4010b8:       48 8d 7c 24 10          lea    0x10(%rsp),%rdi
      4010bd:       e8 76 02 00 00          call   401338 
      4010c2:       85 c0                   test   %eax,%eax
      4010c4:       74 13                   je     4010d9 
      4010c6:       e8 6f 03 00 00          call   40143a 
      4010cb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
      4010d0:       eb 07                   jmp    4010d9 
      4010d2:       b8 00 00 00 00          mov    $0x0,%eax
      4010d7:       eb b2                   jmp    40108b 
      4010d9:       48 8b 44 24 18          mov    0x18(%rsp),%rax
      4010de:       64 48 33 04 25 28 00    xor    %fs:0x28,%rax
      4010e5:       00 00
      4010e7:       74 05                   je     4010ee 
      4010e9:       e8 42 fa ff ff          call   400b30 <__stack_chk_fail@plt>
      4010ee:       48 83 c4 20             add    $0x20,%rsp
      4010f2:       5b                      pop    %rbx
      4010f3:       c3                      ret
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    这里我们直接转换成伪c代码:

    // stack init
    rbx = rdi;
    rax = fs:0x28 (金丝雀值,这里可以看书上的定义)
    *(rsp + 24) = rax;
    eax ^= eax;
    eax = string_length();
    if (eax != 6) {
    	expload_bomb();
    }
    jmp 4010d2;
    40108b:
    ecx = rax + rbx;
    *rsp = cl;
    rdx = *rsp;
    edx &= 0xf;
    edx = *(rdx + 0x4024b0);
    *(rsp + rax + 16) = dl;
    rax += 1;
    if (rax != 6) {
    	jmp 40108b;
    }
    *(rsp + 22) = 0;
    esi = 0x40245e;
    rdi = rsp + 16;
    string_not_equal(rdi, rsi);
    if (eax == 0) {
    	jmp 4010d9;
    }
    explode_bomb();
    jmp 4010d9;
    4010d2:
    eax = 0;
    jmp 40108b;
    4010d9:
    rax = *(rsp + 24);
    if (rax != fs:0x28) {
    	__stack_chk_fail@plt();
    } // 输入的字符串导致金丝雀值发生改变
    // stack init
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    化简一下可以得到:

    // stack init
    rbx = rdi;
    rax = fs:0x28 // 金丝雀值,这里可以看书上的定义
    *(rsp + 24) = rax;
    eax ^= eax;
    eax = string_length();
    if (eax != 6) {
    	expload_bomb();
    }
    for (rax = 0; rax != 6; rax++) {
    	ecx = rax + rbx; // rdi + rax
    	*rsp = cl; // 取出字符
    	rdx = *rsp; 
    	edx &= 0xf; // 把字符的ascii和0xf按位与
    	edx = *(rdx + 0x4024b0); // 
    	*(rsp + rax + 16) = dl; // 将字符放到rsp + rax + 16的位置上
    }
    *(rsp + 22) = 0; // 字符串结尾
    esi = 0x40245e;
    rdi = rsp + 16;
    string_not_equal(rdi, rsi); // 最后得到的rdi要和rsi相同
    if (eax != 0) {
    	explode_bomb();
    }
    rax = *(rsp + 24);
    if (rax != fs:0x28) {
    	__stack_chk_fail@plt();
    } // 输入的字符串导致金丝雀值发生改变
    // stack init
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    首先我们将rsi代表的字符串找出来:
    在这里插入图片描述然后我们将重心放到循环内部,我们可以看到就是取输入的字符串的每一个字符与0xf按位与后再放到栈中,后面要使得按位与后的字符组成的字符串为"flyers",直接查阅ascii码,发现有很多答案,我们取其中一个即可。
    答案:ionefg
    在这里插入图片描述

    phase_6

    00000000004010f4 :
      4010f4:	41 56                	push   %r14
      4010f6:	41 55                	push   %r13
      4010f8:	41 54                	push   %r12
      4010fa:	55                   	push   %rbp
      4010fb:	53                   	push   %rbx
      4010fc:	48 83 ec 50          	sub    $0x50,%rsp
      401100:	49 89 e5             	mov    %rsp,%r13
      401103:	48 89 e6             	mov    %rsp,%rsi
      401106:	e8 51 03 00 00       	call   40145c 
      40110b:	49 89 e6             	mov    %rsp,%r14
      40110e:	41 bc 00 00 00 00    	mov    $0x0,%r12d
      401114:	4c 89 ed             	mov    %r13,%rbp
      401117:	41 8b 45 00          	mov    0x0(%r13),%eax
      40111b:	83 e8 01             	sub    $0x1,%eax
      40111e:	83 f8 05             	cmp    $0x5,%eax
      401121:	76 05                	jbe    401128 
      401123:	e8 12 03 00 00       	call   40143a 
      401128:	41 83 c4 01          	add    $0x1,%r12d
      40112c:	41 83 fc 06          	cmp    $0x6,%r12d
      401130:	74 21                	je     401153 
      401132:	44 89 e3             	mov    %r12d,%ebx
      401135:	48 63 c3             	movslq %ebx,%rax
      401138:	8b 04 84             	mov    (%rsp,%rax,4),%eax
      40113b:	39 45 00             	cmp    %eax,0x0(%rbp)
      40113e:	75 05                	jne    401145 
      401140:	e8 f5 02 00 00       	call   40143a 
      401145:	83 c3 01             	add    $0x1,%ebx
      401148:	83 fb 05             	cmp    $0x5,%ebx
      40114b:	7e e8                	jle    401135 
      40114d:	49 83 c5 04          	add    $0x4,%r13
      401151:	eb c1                	jmp    401114 
      401153:	48 8d 74 24 18       	lea    0x18(%rsp),%rsi
      401158:	4c 89 f0             	mov    %r14,%rax
      40115b:	b9 07 00 00 00       	mov    $0x7,%ecx
      401160:	89 ca                	mov    %ecx,%edx
      401162:	2b 10                	sub    (%rax),%edx
      401164:	89 10                	mov    %edx,(%rax)
      401166:	48 83 c0 04          	add    $0x4,%rax
      40116a:	48 39 f0             	cmp    %rsi,%rax
      40116d:	75 f1                	jne    401160 
      40116f:	be 00 00 00 00       	mov    $0x0,%esi
      401174:	eb 21                	jmp    401197 
      401176:	48 8b 52 08          	mov    0x8(%rdx),%rdx
      40117a:	83 c0 01             	add    $0x1,%eax
      40117d:	39 c8                	cmp    %ecx,%eax
      40117f:	75 f5                	jne    401176 
      401181:	eb 05                	jmp    401188 
      401183:	ba d0 32 60 00       	mov    $0x6032d0,%edx
      401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2)
      40118d:	48 83 c6 04          	add    $0x4,%rsi
      401191:	48 83 fe 18          	cmp    $0x18,%rsi
      401195:	74 14                	je     4011ab 
      401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx
      40119a:	83 f9 01             	cmp    $0x1,%ecx
      40119d:	7e e4                	jle    401183 
      40119f:	b8 01 00 00 00       	mov    $0x1,%eax
      4011a4:	ba d0 32 60 00       	mov    $0x6032d0,%edx
      4011a9:	eb cb                	jmp    401176 
      4011ab:	48 8b 5c 24 20       	mov    0x20(%rsp),%rbx
      4011b0:	48 8d 44 24 28       	lea    0x28(%rsp),%rax
      4011b5:	48 8d 74 24 50       	lea    0x50(%rsp),%rsi
      4011ba:	48 89 d9             	mov    %rbx,%rcx
      4011bd:	48 8b 10             	mov    (%rax),%rdx
      4011c0:	48 89 51 08          	mov    %rdx,0x8(%rcx)
      4011c4:	48 83 c0 08          	add    $0x8,%rax
      4011c8:	48 39 f0             	cmp    %rsi,%rax
      4011cb:	74 05                	je     4011d2 
      4011cd:	48 89 d1             	mov    %rdx,%rcx
      4011d0:	eb eb                	jmp    4011bd 
      4011d2:	48 c7 42 08 00 00 00 	movq   $0x0,0x8(%rdx)
      4011d9:	00 
      4011da:	bd 05 00 00 00       	mov    $0x5,%ebp
      4011df:	48 8b 43 08          	mov    0x8(%rbx),%rax
      4011e3:	8b 00                	mov    (%rax),%eax
      4011e5:	39 03                	cmp    %eax,(%rbx)
      4011e7:	7d 05                	jge    4011ee 
      4011e9:	e8 4c 02 00 00       	call   40143a 
      4011ee:	48 8b 5b 08          	mov    0x8(%rbx),%rbx
      4011f2:	83 ed 01             	sub    $0x1,%ebp
      4011f5:	75 e8                	jne    4011df 
      4011f7:	48 83 c4 50          	add    $0x50,%rsp
      4011fb:	5b                   	pop    %rbx
      4011fc:	5d                   	pop    %rbp
      4011fd:	41 5c                	pop    %r12
      4011ff:	41 5d                	pop    %r13
      401201:	41 5e                	pop    %r14
      401203:	c3                   	ret    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    我们先写出伪c代码:

    phase_6(){
    	// stack init
    	r13 = rsp;
    	rsi = rsp;
    	read_six_numbers(rdi, rsi);
    	r14 = rsp;
    	for (r12d = 0; r12d != 6; r12d++) {
    		rbp = r13;
    		eax = *r13;
    		eax -= 1;
    		if (eax > 5) {
    			explode_bomb();
    		}
    		for (ebx = r12d + 1; ebx <= 5; ebx++) {
    				rax = ebx;
    				eax = *(rsp + 4rax);
    				if (*rbp == eax)
    				{
    					explode_bomb();
    				}		
    		}
    		r13 += 4;
    	}
    	// 这一个循环是判断每个数是否都小于6并且每个数都不能相等
    	rsi = rsp + 24;
    	rax = r14;
    	ecx = 7;
    	for (rax = r14; rax != rsi; rax += 4) {
    		edx = ecx;
    		edx -= *rax;
    		*rax = edx;
    	}
    	// 这个循环是将每个数x都变为7 - x
    	for (rsi = 0; rsi != 24; rsi+=4) {
    		ecx = *(rsp + rsi);
    		edx = 0x6032d0;
    		if(ecx > 1) {
    			for (eax = 1; eax != ecx; eax++) {
    				rdx = *(rdx+8); 
    			}
    		}
    		*(rsp + 2 * rsi + 32) = rdx;
    	}
    	// 这个循环是取每个数如果这个数大于1那么edx = edx + 8
    	// 然后将得到的edx赋给内存的一块区域,可以看到区域的大小应该为8
    	rbx = *(rsp + 32);
    	// 这个就是第一个edx存放的地方
    	rcx = rbx;
    	for (rax = rsp + 40; rax != rsi + 80; rax += 8){
    		rdx = *rax;
    		*(rcx + 8) = rdx;
    		rcx = rdx;
    	}
    	// 这个循环是将rbx+8的指向*rax
    	*(rdx + 8) = 0;
    	for (ebp = 5; ebp != 0; ebp--) {
    		rax = *(rbx + 8);
    		eax = *rax;
    		if (eax < *rbx) {
    			explode_bomb();
    		}
    		rbx = *(rbx + 8);
    	}
    	// 这个循环是在比较rbx + 8和rbx的大小,如果和位置相反则爆炸
    	// stack init
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    再优化:

    void phase_6(char* output)
    {
        int array[6];
        ListNode* node_array[6];
        read_six_numbers(output, array);
        // 数字范围必须为1-6且互不重复
        for (int i = 0; i != 6; i++) {
            int num = array[i];
            num--;
            if ((unsigned int)num > 5)		// 最大为6
                explode_bomb();
            for (int j = i+1; j <= 5; j++) {
                if (array[i] == array[j])	// 每个元素都不重复
                    explode_bomb();
            }
        }
        // 修改 array
    	for (int i = 0; i < 6; i ++) {
            array[i] = (7 - array[i]);
    	}
        // 生成 node_array
    	for (int i = 0; i < 6; i ++) {
            int cur = array[i];
            ListNode* node = 0x6032d0;		// 链表head
            if (cur > 1) {
                for (int j = 1; j < cur; j++) {
                    node = node->next;
                }
            }
            node_array[i] = node;
    	}
        for (int i = 0; i < 5; i++) {
            node_array[i]->next = node_array[i+1];
        }
        ListNode* ptr = node_array[0];
        for (int i = 5; i > 0; i--) {
            if (ptr->val < ptr->next->val)
                explode_bomb();
            ptr = ptr->next;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述
    从这里看,从大到小应该是345612,我们要使得最后链表的值递减,所以应该输入432165,然后转换后为345612,将第三个安排在第一位,第四个安排在第二位…
    在这里插入图片描述

  • 相关阅读:
    javacc之路5---词法分析器技巧
    读卡器串口协议
    PHP 自习室空位查询系统mysql数据库web结构apache计算机软件工程网页wamp计算机毕业设计
    怎么给二维码添加文字或logo?快速美化二维码的使用技巧
    Nginx搭配负载均衡和动静分离:构建高性能Web应用的完美组合
    前端工程化之:webpack3-7(PostCss)
    ECharts 饼图颜色设置教程 - 4 种方式设置饼图颜色
    vscode markdown preview enhanced插件显示图片alt标题注释
    (转)STR 内核做了什么
    LeetCode 每日一题 ---- 【2739.总行驶距离】
  • 原文地址:https://blog.csdn.net/zhy_cx/article/details/126824372