Yozzang의 해킹일기 💻
article thumbnail
Published 2022. 7. 6. 00:19
Pwnable (8. leg) Wargame/Pwnable
728x90

이번 포스트에서는 Pwnable의 leg 문제에 대해 다루겠다.

 


문제 코드는 다음과 같다.

#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;
}

## 문제 해석 :

문제 코드를 살펴 보니, 우리가 입력한 key값이 key1()+key2()+key3()의 값과 같다면 flag를 획득할 수 있는 것으로 보인다.

## 문제 풀이 :

각 key() 함수는 asm() 함수를 통해 어셈블리어 함수를 호출하고 있는 것을 알 수 있다. 그럼 각 함수의 디스어셈블 결과를 확인해보겠다.

# main() : 

main()

key1의 값이 r4에 저장되고, key2의 값이 r3에 저장되고, key3의 값이 r3에 저장되고, key1, key2, key3의 합이 r2에 저장된다는 사실을 알 수 있다.


# key1() : 

key1()

pc 값이 r3에 저장되고, r3값이 r0에 저장된 것을 보아 pc의 값을 알아내면 될 것 같다. pc는 Program Counter의 약자로 레지스터의 일종이다. 또한 pc는 아래와 같이 두 가지 모드가 존재한다.

  1. ASM : 다음 명령어의 주소를 가리킨다.
  2. Thumb : 다다음 명령어의 주소를 가리킨다.

여기서 우리는 해당 시스템이 정확히 어떤 모드를 사용하고 있는지에 대해 모르지만, 테스트해본 결과 Thumb 모드를 사용하고 있다는 것을 확인됐다. 따라서 pc가 가리킨 주소값이 "0x0008ce4"이다.


# key2() :

key2()

pc의 값이 r3에 옮겨진다음에 4를 더하고 다시 r0에 옮겨진것으로 보아 key2()의 반환값이 pc + 4인 것을 알 수 있다. 즉 0x0008d08(pc명령어부터 다다음 번째 명령) + 4 = 0x0008d0c이다.


# key3() :

key3()

lr의 값이 r3에 옮긴 다음에 다시 r0에 옮긴 것으로 보아 lr의 값이 꼭 key3()의 반환값임을 알 수 있다. lr은 Link Register의 약자로 현재 함수가 반환된 직후 프로그램이 처리할 명령어의 반환 주소를 가리킵니다. 즉 main() 함수 중에 key3() 함수가 종료한 후의 바로 다음 명령어의 주소를 가리키고 있으므로 key3()의 반환값 = 0x00008d80이다.

lr 값


여기서 정리하자면,

key1() = 0x0008ce4
key2() = 0x0008d0c
key3() = 0x00008d80

세 값을 더하면 0x001a770라는 값이 나오게 된다. scanf는 %d(정수)를 입력 받고 있기 때문에 이를 10진수로 변환하면 108400라는 값이 나오게 된다.

## 최종 결과 : 

### 공격문 : 108400

### 실행 결과 :

공격 실행

Flag = My daddy has a lot of ARMv5te muscle!

'Wargame > Pwnable' 카테고리의 다른 글

Pwnable (10. shellshock)  (0) 2022.07.08
Pwnable (9. mistake)  (0) 2022.07.07
Pwnable (7. input)  (0) 2022.07.05
Pwnable (6. random)  (0) 2022.07.04
Pwnable (5. passcode)  (0) 2022.07.03
profile

Yozzang의 해킹일기 💻

@요짱

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!