pwnable.kr [leg]
Daddy told me I should study arm.
But I prefer to study my leg!
Download : http://pwnable.kr/bin/leg.c
Download : http://pwnable.kr/bin/leg.asm
ssh leg@pwnable.kr -p2222 (pw:guest)
#include <stdio.h>
#include <fcntl.h>
int key1(){
asm("mov r3, pc\n");
}
int key2(){
asm(
"push {r6}\n"
"add r6, pc, $1\n"
"bx r6\n"
".code 16\n"
"mov r3, pc\n"
"add r3, $0x4\n"
"push {r3}\n"
"pop {pc}\n"
".code 32\n"
"pop {r6}\n"
);
}
int key3(){
asm("mov r3, lr\n");
}
int main(){
int key=0;
printf("Daddy has very strong arm! : ");
scanf("%d", &key);
if( (key1()+key2()+key3()) == key ){
printf("Congratz!\n");
int fd = open("flag", O_RDONLY);
char buf[100];
int r = read(fd, buf, 100);
write(0, buf, r);
}
else{
printf("I have strong leg :P\n");
}
return 0;
}
key1(), key2(), key3()은 asm 함수로 어셈블리로 되어있고...
main()보면 입력할 정수 key가 key1()+key2()+key3()과 동일해야 하므로 if문에서 비교하는 저 셋을 합친 값이 어떻게 되는지 gdb로 확인해보면 알 수 있을듯
gdb로 확인한 결과가 leg.asm에 저장되어 있음
main()보면 cmp 비교에서 r2랑 r3랑 비교함
r2가 key1()+key2()+key3()일거고
위에 key1, key2, key3의 함수 들어갔다가 나와서 모두 r0의 값을 r3, r4에 넣어서 add하는 등의 전처리를 진행함
고로 key 함수들은 결과값을 r0에 저장한다는 소리 => 각 key 함수들의 r0를 확인하자.
key1()에서 r0는 r3에서 왔고, r3는 pc에서 옴.
pc는 opcode의 pipe line 작업을 위한 다다음 주소를 저장하는 레지스터.
그렇다면 key+8에서의 pc는 key+16인 0x00008ce4이겠다. 이게 key1()의 r0임
key2()도 r0는 r3에서 왔고, r3는 pc+4에서 옴
pc는 key+20에의 pc 이므로 0x00008d08이고 여기서 +4한 값은 0x00008d0c임 key2()에서의 r0값은 0x8d0c
마지막 key3()에서는 pc가 아니라 lr에서 옴
lr는 함수 끝나면 되돌아갈 실행 주소를 담고 있음. 즉, key3()이 끝나고 main에서 다음 주소라는 뜻
key3 끝나면 mian+68로 감. 고로 key3()의 r0는 결국 0x8d80이 될 것임
최종 결산 두둥탁,
key1()+key2()+key3() = 0x00008ce4 + 0x00008d0c + 0x00008d80 = 1A770=108400(10진수)
key 입력할 때 정수로 받으니까(%d) 10진수로 108400 쳐넣으면 되겠습니다~