prob1
main 함수가 보인다.
main 함수를 확인해보았다.
sub으로 스택을 확장하고 rbp-0x8에 fs:0x28을 넣는다. 이게 스택 카나리다.
마지막에 fs:0x28과 rbp-0x8을 비교하는 것을 볼 수 있다.
main+28에 puts를 호출한다. edi에 0x4007d4가 들어간다.
0x4007d4가 문자열이라고 추측할 수 있다.
__isoc99_scanf@plt는 scanf의 plt를 말한다.
이 plt가 libc의 scanf의 실제 주소를 가리키는 got를 가리킨다.
edi는 아마 포맷 스트링이 될 것이고, rbp-0xc는 저장되는 위치를 말할 것이라고 예측할 수 있다.
그리고 cmp를 통해서 rbp-0xc부터 4바이트와 0xdeadbeef와 비교한다.
다르면 끝내고 아니면 flag generator를 호출한다.
그리고 그 리턴 값을 rdi에 넣고 puts@plt를 호출한다.
마지막엔 함수 프롤로그를 확인할 수 있다.
breakpoint를 걸었다.
rdi를 보면 input any number가 들어가있는 것을 확인할 수 있다.
다음 bp로 이동하고 포맷 스트링을 확인하면 %d인 것을 알 수 있다.
scanf로 받은 정수는 rbp-0xc에 저장되고 cmp로 0xdeadbeef랑 비교했으니 0xdeadbeef를 부호있는 10진수로 바꿔줘서 넣어주면 된다. 크기는 4바이트이니 int형이라고 생각하면 된다.
int형으로 바꿔서 출력해줬고 입력값을 똑같이 줬다.
flag_generator의 리턴값이 출력된다.
prob2
main+8은 스택 카나리여서 무시하고, edi에 0xfeedc0de를 넣고 srand를 부르는 것을 볼 수 있다.
이 srand는 나중에 rand의 시드값을 설정해주는 함수다.
시드 값이 같으면 rand는 동일한 값을 리턴한다.
srand로 시드 값을 설정해주고 0x0을 rbp-0x10에 push 한다. 스택 카나리 바로 아래에 push 된다.
그리고 바로 main+111로 점프한다.
rbp-0x10 4바이트와 0x13를 cmp로 비교한다.
기본적으로 cmp는 비교를 두 개의 operand를 빼서 비교하기 때문에 대소 관계를 비교할 수 있다.
0x13보다 작거나 같으면 main+42로 점프한다.
더 크면 0x4008ec의 포맷 스트링으로 입력을 받아서 rbp-0x14에 저장한다.
rbp-0x14와 0xdeadface와 비교한다.
비교해서 다르면 main+194로 점프한다.
main+42에서부터는 edi에 0x4008d4를 넣고 puts@plt를 부른다.
0x4008d4가 스트링임을 짐작할 수 있다.
그다음 rbp-0xc에 rand의 리턴 값을 넣는다.
0x4008d4는 포맷 스트링이라고 짐작할 수 있다.
그리고 rbp-0x14부터 저장한다.
scanf로 입력받은 rbp-0x14부터 4바이트를 아까 rand의 리턴 값 rbp-0xc와 비교한다.
같으면 main+107로 점프한다.
rbp-0x10에 1 더하고 0x13과 다시 비교한다.
틀리면 je가 안되니 그대로 puts로 0x4008e를 출력하고 main+209로 점프한다.
main+209에는 스택 카나리를 검사하고 함수 에필로그가 있다.
결국은 srand(0xfeedc0de)하고 rand()를 0x14개 뽑아서 다 맞추고 0xdeadface를 포맷 스트링에 맞게 넣으면 된다.
scanf의 포맷 스트링은 main+77이랑 main+144에서 둘 다 %d이다.
rodata 섹션에 %d가 있다.
decimal로 넣으면 된다.
시드 넣고 rand 값을 뽑아준다.
앞에서 출력해준 걸 받아서 배열에 넣고 0x14번 맞춰주고 0xdeadface를 decimal로 바꿔서 보내준다.
./c | python a.py
나온다.
'Layer7 동아리 과제' 카테고리의 다른 글
리버싱 6차시 과제 (0) | 2022.08.02 |
---|---|
리버싱 5차시 과제 (0) | 2022.07.31 |
리버싱 3차시 과제 (0) | 2022.07.23 |
리버싱 2차시 과제 (0) | 2022.07.20 |
하드웨어 3, 4차시 과제 (0) | 2022.06.19 |