leg@pwnable.kr으로 접속하면 다음과 같이 출력된다.
평소와 같이 쉘이 실행되는 모습이 아니다.
그래서 직접 다운로드 링크에 접속하여 코드를 확인했다.
복붙하면 개행처리 되지 않아 예쁘게 나오지 않으므로 부득이하게 캡처를 했다.
쉘 내부에서 몇가지 명령어가 되는 것을 확인했다. leg 파일이 있는 걸로 봐서
입력 후에 flag가 열리는 구조 인것 같다.
그렇다면 위의 코드를 열심히 분석해보자
leg.c의 코드를 보면 key1()+key2()+key3() 가 key과 같을 시에 flag를 열 수 있는 구조이다.
0x00008d84 <+72>: add r2, r4, r3
0x00008d8c <+80>: cmp r2, r3
해당 부분을 보면 r2에 key가 저장되어 있는 것 같다.
모르는 것을 잠깐 정리해보자.
sp(Stack Pointer register) : 스택의 최상단을 가리키는 포인터로 사용
pc는 개념이 조금 어렵다;;;
CPU가 명령어 하나를 수행할 떄 fetch > decode > execute 의 절차를 수행한다.
2개 opcode를 실행하려면 fetch > decode > execute > fetch > decode > execute 총 6번의 작업이 필요한 것이다.
하지만 pipe line 을 사용한다면,
1 | 2 | 3 | 4 | 5 |
fetch | decode | execute | ||
fetch | decode | execute | ||
fetch | decode | execute |
이렇게 병렬적으로 수행하면 6번의 작업을 4번으로 단축시킬 수가 있다.
결과적으로 pc는 fetch할 주소를 담고 있다는 것이다. 결국 다다음번쨰 명령어의 주소를 담고 있다는 것이다!
pipe line은 가장 기본이 되는 3단계가 있고, 조금 더 세부적으로 나누면 5단계, 8단계, 13단계가 있다.
ARM7은 3단계, ARM9는 5단계, ARM11은 8단계, CortexA8은 13단계이다.
다만 이건 정리 수준이고, 나중에 pipe line에 대한 공부를 본격적으로 해야할 것 같다. 상당히 중요한 내용이다.
다음부터 write-up을 참고한다.
key1() 함수를 보면 r3에 pc를 넣고, 다시 r0에 r3를 대입한다. 그래서 pc는 다다음에 실행할 코드이므로,
따라서 0x00008ce4가 pc 값이다.
다음 key2()함수를 보면, r3에 pc를 대입하고, 그 값에 4를 더한다. 그래서 pc+4를 하면 r3가 되는 것이고, 다시 r0에 삽입한다.
pc = 0x00008d08 이므로 +4 는 0x00008d0c가 된다.
key3()함수는 조금 어려운 형태다. r0 <- r3 <- lr 형태인데, lr 이 뭐지?
lr(Link Resister)은 함수 호출 전에 다시 되돌아가 실행할 주소를 담고 있다.
함수 실행 주소는 0x00008d7c 부분이고, 0x00008d8b에서 lr를 호출하며 메인함수의 다음 opcode를 실행한다.
따라서 0x00008d80 mov r3, r0가 lr주소가 되는 것이다.
그러므로 key1=0x00008ce4, key2=0x00008d0c, key3=0x00008d80이 되고, 모두를 더하면 0x0001a770이 된다.
코드에서 정수값을 입력받기 때문에 108400를 입력하면 된다.
My daddy has a lot of ARMv5te muscle!
갑자기 ARM개념이 나와서 매우 당황했다. 하지만 예전에 들었던 수업을 복습해보는 좋은 기회가 되었다고 생각한다. 나름 머리 싸맸더니 그래도 어셈블리에 한걸음 가까워졌다. 나중에 pipe line을 더 공부해보자.
'pwnable' 카테고리의 다른 글
[Toddler's Bottle] cmd1 (0) | 2024.05.11 |
---|---|
[Toddler's Bottle] lotto (0) | 2024.05.11 |
[Toddler's Bottle] blukat (0) | 2024.05.11 |
[Toddler's Bottle] input (1) | 2024.05.11 |
[Toddler's Bottle] asm (0) | 2024.05.11 |