The first question is relatively simple, but this dish chicken has also been made for two hours (')(
Firstly, open the bomb.s file which has been disassembled in advance. Through bomb.c, we know that each level is a function. Their name is phase_x. X represents the number of the level. If the input of a level is incorrect, the explode_bomb will be detonated. Let's first look at the lines of main function.
400e1e: bf 38 23 40 00 mov $0x402338,%edi 400e23: e8 e8 fc ff ff callq 400b10 <puts@plt> 400e28: bf 78 23 40 00 mov $0x402378,%edi 400e2d: e8 de fc ff ff callq 400b10 <puts@plt> 400e32: e8 67 06 00 00 callq 40149e <read_line> 400e37: 48 89 c7 mov %rax,%rdi 400e3a: e8 a1 00 00 00 callq 400ee0 <phase_1> 400e3f: e8 80 07 00 00 callq 4015c4 <phase_defused> 400e44: bf a8 23 40 00 mov $0x4023a8,%edi
Open gdb, break the line first * 0x400e23, then run up. Here you can see that the function put is called. Register% edi stores the first parameter of the function. We print out the results of the function x/s 0x402338 and x/s 0x402378, and find out the string output after running bomb. It means that the first pass begins here.
Since the return value is in% rax, here mov% rax% RDI indicates that the input is passed to phase_1. break phase_1 in gdb.
0000000000400ee0 <phase_1>: 400ee0: 48 83 ec 08 sub $0x8,%rsp 400ee4: be 00 24 40 00 mov $0x402400,%esi 400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal> 400eee: 85 c0 test %eax,%eax 400ef0: 74 05 je 400ef7 <phase_1+0x17> 400ef2: e8 43 05 00 00 callq 40143a <explode_bomb> 400ef7: 48 83 c4 08 add $0x8,%rsp 400efb: c3 retq
Through the code here, we can analyze whether the input string is equal to the string stored in 0x402400 by calling string_not_equal to determine whether it is explode_bomb. Through this function name, you can also know that you must enter the same string as 0x402400 to pass the first pass. So break *0x400ee9 here, and then x/s 0x402400 prints out the string here. I'm Border relations with Canada have never been better. Then I enter the string, and the first pass is over.~
string_not_equal
Although this will pass, but I am still curious about the code here, after all, it is learning, look at the code here familiar with assembly.
0000000000401338 <strings_not_equal>: 401338: 41 54 push %r12 40133a: 55 push %rbp 40133b: 53 push %rbx 40133c: 48 89 fb mov %rdi,%rbx 40133f: 48 89 f5 mov %rsi,%rbp 401342: e8 d4 ff ff ff callq 40131b <string_length> 401347: 41 89 c4 mov %eax,%r12d 40134a: 48 89 ef mov %rbp,%rdi 40134d: e8 c9 ff ff ff callq 40131b <string_length> 401352: ba 01 00 00 00 mov $0x1,%edx 401357: 41 39 c4 cmp %eax,%r12d 40135a: 75 3f jne 40139b <strings_not_equal+0x63> 40135c: 0f b6 03 movzbl (%rbx),%eax 40135f: 84 c0 test %al,%al 401361: 74 25 je 401388 <strings_not_equal+0x50> 401363: 3a 45 00 cmp 0x0(%rbp),%al 401366: 74 0a je 401372 <strings_not_equal+0x3a> 401368: eb 25 jmp 40138f <strings_not_equal+0x57> 40136a: 3a 45 00 cmp 0x0(%rbp),%al 40136d: 0f 1f 00 nopl (%rax) 401370: 75 24 jne 401396 <strings_not_equal+0x5e> 401372: 48 83 c3 01 add $0x1,%rbx 401376: 48 83 c5 01 add $0x1,%rbp 40137a: 0f b6 03 movzbl (%rbx),%eax 40137d: 84 c0 test %al,%al 40137f: 75 e9 jne 40136a <strings_not_equal+0x32> 401381: ba 00 00 00 00 mov $0x0,%edx 401386: eb 13 jmp 40139b <strings_not_equal+0x63> 401388: ba 00 00 00 00 mov $0x0,%edx 40138d: eb 0c jmp 40139b <strings_not_equal+0x63> 40138f: ba 01 00 00 00 mov $0x1,%edx 401394: eb 05 jmp 40139b <strings_not_equal+0x63> 401396: ba 01 00 00 00 mov $0x1,%edx 40139b: 89 d0 mov %edx,%eax 40139d: 5b pop %rbx 40139e: 5d pop %rbp 40139f: 41 5c pop %r12 4013a1: c3 retq
Looking at the code, I found that it is very consistent with the book, and% r12,% rbp,% rbx are registers saved by the callee.
Firstly, 0x401342 ~ 0x40135a is used to judge whether they are the same length. If the length is different, then they are not the same string. Mov $0x1,% EDX and mov% edx,% eax returns 1.
Lines 0x405c ~ 0x401361 determine whether the first character of the input string is gill 0. Since the length of the command has been determined to be the same, if the first character of one of the strings is 0, then the other must be the same (all strings must contain a 0), so it returns 0 directly here.
0x401361 ~ 0x40137f is a loop, it traverses two strings, each character is the same, until encounter gill 0.
string_length
000000000040131b <string_length>: 40131b: 80 3f 00 cmpb $0x0,(%rdi) 40131e: 74 12 je 401332 <string_length+0x17> 401320: 48 89 fa mov %rdi,%rdx 401323: 48 83 c2 01 add $0x1,%rdx 401327: 89 d0 mov %edx,%eax 401329: 29 f8 sub %edi,%eax 40132b: 80 3a 00 cmpb $0x0,(%rdx) 40132e: 75 f3 jne 401323 <string_length+0x8> 401330: f3 c3 repz retq 401332: b8 00 00 00 00 mov $0x0,%eax 401337: c3 retq
This function is relatively simple, in fact, is to find the location of 0, and then return the difference between the other first address, that is, length. This translation can be written in C.
int string_length(char *s) { char *b = a; while (*b != 0) b = b + 1; return (int) (b - a); }
This article is the author's understanding and summary when reading "Deep Understanding of Computer Systems" and completing bomb lab. It is hereby recorded and has been read in the future. At the same time, I would like to share this knowledge with all my colleagues. Due to the limited level of the author, if there are any mistakes, I would like to thank you for your kind advice.