포너블 8번째 leg 문제에 대해 풀어볼 것이다.
arm에 대해 배우다는 내용이 담겨있다.
먼저 ssh를 통해 접속을 해보았다. 부팅과 관련된 말들이 나타났고,
ls를 해보니 leg라는 실행파일이 있었다.
leg 파일을 실행해보니
"Daddy has very strong arm! :" 이라 뜨고 flag 값을 입력해주어야하는 구조이다.
다음은 leg.c 소스코드이다.
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;
}
키를 구하는 함수는 arm 기반 어셈블리어(asm)이고, 키 변수를 초기화하고 입력값을 저장한다.
key1,2,3에서 각각 나온 값을 모두 더한 값이 그 입력값과 같아면 성공메시지와 함께 flag 파일을 열어 읽는다.
아닐 경우 오답 메시지를 띄운다.
"key1()+key2()+key3()) == key" 이 부분이 핵심이다.
따라서 디스어셈블을 통해 값을 구해보아야한다.
메인함수에서는 먼저 key1 함수로 들어가서 r0 값을 얻어와 r4에 담고
동일한 방법으로 key2, key3에서 값을 받아 온 뒤 더한다.
key1 함수에서는 키 값은 00008ce4이고 과정은 위와 같다.
r0 값을 알아야하는데 r0은 pc값 -> r3 값 -> r0 순서이다.
그대로 값을 옮겨오기 때문에 pc 값을 안다면 key1 값을 알 수 있다.
CPU는 명령어를 수행할 때 fectch-decode-execute 세 과정을 거친다.
두개의 명령어(opcode)를 수행하려면 총 6번의 과정이 필요하지만 파이프라인잉란 걸 사용하면
fetch-decode(fetch)-execute(decode)-execute 총 4번의 과정을 걸친다고 한다. 이때 fetch 할 주소를 담는게 pc이다.
결국 pc라는 프로그램 카운터는 다음 명령어인 fetch를 가리키고 있어, arm 기반 어셈블리의 경우 32비트가 1워드이므로 pc는 항상 8만큼 앞서가고 잇다. 스택구조에서 한칸이 4이므로 두칸 밑을 가리키고 있다고 생각하면된다.
그러면 00008ce4가 pc 값이 된다.
key2()함수는 키값이 00008d0c이다.
키2는 r0에 r3값을 대입하고 r3은 pc 값에 4를 더한 값이 담겨져 있어 pc+4+8이기 때문에
pc 값을 불러올때 00008d08에서 4를 더한 00008d0c이다.
key3()함수는 키값이 00008d80이다.
r0의 값은 결과적으로 lr 값이 들어간다.이값은 bl, b 등의 명령어로 주소를 분기하여 점프해왔을때 다시 돌아와
실행할 리턴 주소를 가리킨다.
flag값은 이 키 1,2,3 값을 모두 더한 값으로 10진수로 변환해주어야한다.
8ce4 + 8d0c + 8d80 = 1A770
이를 10진수로 변환하면 108400이다.
'CTF 스터디' 카테고리의 다른 글
[pwnable.kr] 10번_ shellshock 풀이 (0) | 2021.05.03 |
---|---|
[pwnable.kr] 9번_ mistake 풀이 (0) | 2021.04.23 |
[pwnable.kr] 7번_input 풀이 (0) | 2021.04.05 |
[pwnable.kr] 6번_random 풀이 (0) | 2021.04.05 |
[pwnable.kr] 5번_ passcode 풀이 (0) | 2021.03.31 |