0x0000000000401136 <+0>: endbr64
0x000000000040113a <+4>: push %rbp
0x000000000040113b <+5>: mov %rsp,%rbp
0x000000000040113e <+8>: sub $0x10,%rsp
0x0000000000401142 <+12>: movq $0x402004,-0x8(%rbp)
0x000000000040114a <+20>: mov -0x8(%rbp),%rax
0x000000000040114e <+24>: mov %rax,%rsi
0x0000000000401151 <+27>: mov $0x402015,%edi
0x0000000000401156 <+32>: mov $0x0,%eax
0x000000000040115b <+37>: callq 0x401040 <printf@plt>
0x0000000000401160 <+42>: mov $0x0,%eax
0x0000000000401165 <+47>: leaveq
0x0000000000401166 <+48>: retq
위는 handray1 파일을 gdb로 disassemble한 결과이다.
#include <stdio.h>
int main(){
char* a = "handray is easy!";
{{guess1}}("%s",{{guess2}});
}
// flag = {{guess1}}{{guess2}} (공백없이) ex)strcmpa
문제의 힌트는 위와 같다.
그럼 어셈블리를 다시 살펴보면 37라인 "printf"함수를 호출하고 있다.
따라서 flag는 printf와 a변수 즉, printfa
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000401156 <+0>: endbr64
0x000000000040115a <+4>: push %rbp
0x000000000040115b <+5>: mov %rsp,%rbp
0x000000000040115e <+8>: sub $0x10,%rsp
0x0000000000401162 <+12>: lea -0x4(%rbp),%rax
0x0000000000401166 <+16>: mov %rax,%rsi
0x0000000000401169 <+19>: mov $0x402004,%edi
0x000000000040116e <+24>: mov $0x0,%eax
0x0000000000401173 <+29>: callq 0x401060 <__isoc99_scanf@plt>
0x0000000000401178 <+34>: mov -0x4(%rbp),%eax
0x000000000040117b <+37>: and $0x1,%eax
0x000000000040117e <+40>: test %eax,%eax
0x0000000000401180 <+42>: jne 0x401193 <main+61>
0x0000000000401182 <+44>: mov $0x402007,%edi
0x0000000000401187 <+49>: mov $0x0,%eax
0x000000000040118c <+54>: callq 0x401050 <printf@plt>
0x0000000000401191 <+59>: jmp 0x4011a2 <main+76>
0x0000000000401193 <+61>: mov $0x40200c,%edi
0x0000000000401198 <+66>: mov $0x0,%eax
0x000000000040119d <+71>: callq 0x401050 <printf@plt>
0x00000000004011a2 <+76>: mov $0x0,%eax
0x00000000004011a7 <+81>: leaveq
--Type <RET> for more, q to quit, c to continue without paging--
0x00000000004011a8 <+82>: retq
End of assembler dump.
(gdb) disassemble __isoc99_scanf
Dump of assembler code for function __isoc99_scanf@plt:
0x0000000000401060 <+0>: endbr64
0x0000000000401064 <+4>: bnd
Hint : ___판별기 (판별기 까지 작성해주세요!)
문제의 힌트는 위와 같다.
코드를 쭉 읽던 중 눈에 들어오는 코드가 있다.
0x000000000040117b <+37>: and $0x1,%eax
eax에 저장되어있는 값과 0x1을 and 조건을 통해 연산한다.
꼴랑 1 들어있는 값과 and 연산시에는 1 또는 0만 남는다. 정확히는 짝수면 0, 홀수면 1이 출력된다.
0x000000000040117e <+40>: test %eax,%eax
이후 eax에 들어있는 값이 0인지 확인한다.
이후 각각 0 또는 1일시 지정된 부분으로 점프해서 printf문을 통해 출력하고 있다.
결과적으로 홀수판별기, 짝수판별기 등 많이 입력해본 결과 정답은 홀짝판별기였다.
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000401136 <+0>: endbr64
0x000000000040113a <+4>: push %rbp
0x000000000040113b <+5>: mov %rsp,%rbp
0x000000000040113e <+8>: sub $0x10,%rsp
0x0000000000401142 <+12>: movq $0x402004,-0x8(%rbp)
0x000000000040114a <+20>: movq $0x402013,-0x10(%rbp)
0x0000000000401152 <+28>: mov -0x8(%rbp),%rax
0x0000000000401156 <+32>: add $0x1,%rax
0x000000000040115a <+36>: movzbl (%rax),%edx
0x000000000040115d <+39>: mov -0x10(%rbp),%rax
0x0000000000401161 <+43>: add $0x1,%rax
0x0000000000401165 <+47>: movzbl (%rax),%eax
0x0000000000401168 <+50>: cmp %al,%dl
0x000000000040116a <+52>: jne 0x40117b <main+69>
0x000000000040116c <+54>: mov $0x402026,%edi
0x0000000000401171 <+59>: mov $0x0,%eax
0x0000000000401176 <+64>: callq 0x401040 <printf@plt>
0x000000000040117b <+69>: mov -0x8(%rbp),%rax
0x000000000040117f <+73>: add $0x4,%rax
0x0000000000401183 <+77>: movzbl (%rax),%edx
0x0000000000401186 <+80>: mov -0x10(%rbp),%rax
0x000000000040118a <+84>: add $0x4,%rax
--Type <RET> for more, q to quit, c to continue without paging--c
0x000000000040118e <+88>: movzbl (%rax),%eax
0x0000000000401191 <+91>: cmp %al,%dl
0x0000000000401193 <+93>: jne 0x4011a4 <main+110>
0x0000000000401195 <+95>: mov $0x402032,%edi
0x000000000040119a <+100>: mov $0x0,%eax
0x000000000040119f <+105>: callq 0x401040 <printf@plt>
0x00000000004011a4 <+110>: mov $0x0,%eax
0x00000000004011a9 <+115>: leaveq
0x00000000004011aa <+116>: retq
0x0000000000401136 <+0>: endbr64
0x000000000040113a <+4>: push %rbp
0x000000000040113b <+5>: mov %rsp,%rbp
0x000000000040113e <+8>: sub $0x10,%rsp
스택 프레임 설정: 현재 rbp를 스택에 저장하고, rsp를 rbp로 설정하여 새로운 스택 프레임을 만듦.
0x0000000000401142 <+12>: movq $0x402004,-0x8(%rbp)
0x000000000040114a <+20>: movq $0x402013,-0x10(%rbp)
문자열 주소 저장: 첫 번째와 두 번째 문자열의 주소를 각각 -0x8(%rbp)와 -0x10(%rbp)에 저장함.
int main() {
char *str1 = "ABCD";
char *str2 = "ABEF";
C 코드: str1과 str2에 문자열 주소를 저장함.
0x0000000000401152 <+28>: mov -0x8(%rbp),%rax
0x0000000000401156 <+32>: add $0x1,%rax
0x000000000040115a <+36>: movzbl (%rax),%edx
0x000000000040115d <+39>: mov -0x10(%rbp),%rax
0x0000000000401161 <+43>: add $0x1,%rax
0x0000000000401165 <+47>: movzbl (%rax),%eax
0x0000000000401168 <+50>: cmp %al,%dl
0x000000000040116a <+52>: jne 0x40117b <main+69>
두 번째 문자 비교: str1[1]과 str2[1]을 비교하고, 같으면 메시지를 출력하는 코드, 다르면 점프
if (str1[1] != str2[1]) {
printf("Second characters do not match.\n");
}
C 코드: 두 번째 문자가 다를 경우 스킵, 같을 경우 같다고 출력
0x000000000040117b <+69>: mov -0x8(%rbp),%rax
0x000000000040117f <+73>: add $0x4,%rax
0x0000000000401183 <+77>: movzbl (%rax),%edx
0x0000000000401186 <+80>: mov -0x10(%rbp),%rax
0x000000000040118a <+84>: add $0x4,%rax
0x000000000040118e <+88>: movzbl (%rax),%eax
0x0000000000401191 <+91>: cmp %al,%dl
0x0000000000401193 <+93>: jne 0x4011a4 <main+110>
다섯 번째 문자 비교: str1[4]과 str2[4]을 비교하고, 같으면 메시지를 출력하는 코드, 다르면 점프
if (str1[4] != str2[4]) {
printf("Fifth characters do not match.\n");
}
C 코드: 다섯 번째 문자가 다를 경우 스킵, 같을 경우 같다고 출력
결과적으로 유추한 C코드는 다음과 같다
#include <stdio.h> #include <string.h> int main() { char str1 = "ABCD"; charstr2 = "ABEF"; if (str1[1] == str2[1]) { printf("Second character matches.\n"); } if (str1[4] == str2[4]) { printf("Fifth character matches.\n"); } return 0; }