[Pwnable.kr] leg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#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;
}
 
cs


접속해서보면 gdb를 사용할 수 없습니다. 사용할 수 있으면 그냥 메모리를 들여다봐서 key를 보면 되니까 쉬울텐데 아쉽네요. 차근차근 풀어나가야할 것 같습니다. key1(), key2(), key3()이 어떤 값을 반환하는지 알아야겠네요.


INTEL/AT&T에서는 함수의 리턴값을 eax에 두는데 arm에서는 r0에 둡니다. 이는 *main+48, +56, +68에서도 확인 가능합니다.

pc는 program counter이고, 다음에 실행할 주소를 담고 있는데, 독특하게도 현재 주소의 +4가 아니라 +8을 가지고 있습니다. 이는 CPU가 Fetch/Decode/Execute를 동시에 진행하기 때문인데, 즉


Fetch - 0x1000 // Decode - 0x1004 // Execute - 0x1008

Fetch - 0x1004 // Decode - 0x1008 // Execute - 0x100C

.
.
.
이런식으로 진행하기 때문에 Execute 되는 주소(=pc)는 Fetch하는 주소보다 8이 큰 값입니다.
lr은 link register이고, 함수를 호출하거나 어딘가로 점프를 했을 떄 돌아올 주소를 넣어두는 레지스터입니다.
그러면 key1의 값은 0x8cdc + 8 = 0x8ce4
key2의 값은 0x8d04 + 8 + 4 = 0x8d0c
key3의 값은 0x8d80(*main+68으로 돌아올 것이므로)입니다.

0x8ce4+0x8d0c+0x8d80 = 108400을 입력해주면 됩니다.



'워게임 > Pwnable.kr' 카테고리의 다른 글

[Pwnable.kr] coin1  (3) 2018.01.15
[Pwnable.kr] shellshock  (0) 2018.01.15
[Pwnable.kr] mistake  (0) 2018.01.15
[Pwnable.kr] input  (0) 2018.01.15
[Pwnable.kr] random  (0) 2018.01.15
[Pwnable.kr] passcode  (0) 2018.01.15
  Comments