leg - 2 pt
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)
leg.c를 봅시다.
#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부터 3까지의 함수들은 ARM 어셈블리어로 작성이 되었네요.
먼저 main함수를 보면 위 3개의 함수값을 모두 더한값을 맞추면 플래그를 얻을 수 있는 것 같습니다!
main함수의 어셈코드도 봅시다!
0x00008d68 <+44>: bl 0x8cd4 <key1> 0x00008d6c <+48>: mov r4, r0 0x00008d70 <+52>: bl 0x8cf0 <key2> 0x00008d74 <+56>: mov r3, r0 0x00008d78 <+60>: add r4, r4, r3 0x00008d7c <+64>: bl 0x8d20 <key3> 0x00008d80 <+68>: mov r3, r0 0x00008d84 <+72>: add r2, r4, r3 0x00008d88 <+76>: ldr r3, [r11, #-16] 0x00008d8c <+80>: cmp r2, r3
함수를 통해 구한 r0값을 모두 더해서 최종적으로 r2에 들어가는 것을 알 수 있네요.
그럼 각 함수를 보겠습니다.
int key1(){ asm("mov r3, pc\n"); }
(gdb) disass key1 Dump of assembler code for function key1: 0x00008cd4 <+0>: push {r11} ; (str r11, [sp, #-4]!) 0x00008cd8 <+4>: add r11, sp, #0 0x00008cdc <+8>: mov r3, pc 0x00008ce0 <+12>: mov r0, r3 0x00008ce4 <+16>: sub sp, r11, #0 0x00008ce8 <+20>: pop {r11} ; (ldr r11, [sp], #4) 0x00008cec <+24>: bx lr End of assembler dump.
key1함수의 c와 어쎔코드입니다.
pc라는 값을 r3에 넣고 다시 r3를 r0에 넣었습니다.
그러면 pc라는 값이 key1의 값이 되겠네요.
그럼 pc가 뭔지 공부하고 옵시다!
cpu가 명령어 하나를 수행할 때 fetch > decode > execute 의 과정을 거친다고 합니다.
2개의 opcode를 실행하려면 fetch > decode > execute > fetch > decode > execute 총 6번의 작업이 필요하죠.
하지만 pipe line라는 것을 이용해서
1 |
2 |
3 |
4 |
fetch |
decode |
execute |
|
|
fetch |
decode |
execute |
이렇게 병렬적으로 단계를 수행하면 2개의 opcode를 실행할때 6번의 작업이 필요했던것을 4번으로 줄일 수 있습니다.
직렬보다 효율적이죠.
pc는 fetch할 주소를 담고 있습니다.
현재 명령어가 execute단계라면, 다음 명령어는 decode단계, 그 다음 명령어는 fetch 단계이겠죠.
그래서 pc는 다다음번째 명령어의 주소를 담고 있게 됩니다.
key1 함수에서 pc의 값은 0x00008ce4 가 되겠네요.
이제 key2를 봅시다.
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" ); }
(gdb) disass key2 Dump of assembler code for function key2: 0x00008cf0 <+0>: push {r11} ; (str r11, [sp, #-4]!) 0x00008cf4 <+4>: add r11, sp, #0 0x00008cf8 <+8>: push {r6} ; (str r6, [sp, #-4]!) 0x00008cfc <+12>: add r6, pc, #1 0x00008d00 <+16>: bx r6 0x00008d04 <+20>: mov r3, pc 0x00008d06 <+22>: adds r3, #4 0x00008d08 <+24>: push {r3} 0x00008d0a <+26>: pop {pc} 0x00008d0c <+28>: pop {r6} ; (ldr r6, [sp], #4) 0x00008d10 <+32>: mov r0, r3 0x00008d14 <+36>: sub sp, r11, #0 0x00008d18 <+40>: pop {r11} ; (ldr r11, [sp], #4) 0x00008d1c <+44>: bx lr End of assembler dump.
r3에 pc값(0x00008d08)을 대입하고, 4를 더해서 r0에 대입하네요.
key2의 값은 0x8d08 + 4 = 0x8d0c !!!
key3를 봅시다.
int key3(){ asm("mov r3, lr\n"); }
(gdb) disass key3 Dump of assembler code for function key3: 0x00008d20 <+0>: push {r11} ; (str r11, [sp, #-4]!) 0x00008d24 <+4>: add r11, sp, #0 0x00008d28 <+8>: mov r3, lr 0x00008d2c <+12>: mov r0, r3 0x00008d30 <+16>: sub sp, r11, #0 0x00008d34 <+20>: pop {r11} ; (ldr r11, [sp], #4) 0x00008d38 <+24>: bx lr End of assembler dump.
lr이라는 값을 r3에 대입하고 r3의 값을 r0에 대입하네요.
그러면 lr이라는 값을 구하면 될 것 같네요.
lr은 함수 호출 전에 다시 되돌아가 실행할 주소를 담고 있다고 합니다.
main함수를 보면,
0x00008d7c <+64>: bl 0x8d20 <key3> 0x00008d80 <+68>: mov r3, r0 0x00008d84 <+72>: add r2, r4, r3
lr의 값은 0x00008d80 이 되겠네요.
3개 모두 구했습니다!!
key1 | 0x8ce4
key2 | 0x8d0c
key3 | 0x8d80
모두 더하면 0x1a770 이네요.
그럼 이제 플래그를 구합시다!
프로그램에서 정수값으로 입력을 받기 때문에 108400을 입력하겠습니다.
/ $ ./leg
Daddy has very strong arm! : 108400
Congratz!
My daddy has a lot of ARMv5te muscle!
'WAR GAME > Pwnable.kr' 카테고리의 다른 글
pwnable.kr [shellshock] 풀이 (0) | 2018.03.08 |
---|---|
pwnable.kr [mistake] 풀이 (0) | 2018.03.08 |
pwnable.kr [input] 풀이 (0) | 2018.03.06 |
pwnable.kr [random] 풀이 (0) | 2018.02.26 |
pwnable.kr [passcode] 풀이 (0) | 2018.02.26 |