블로그 이전했습니다. https://jeongzero.oopy.io/
[pwnble.kr] leg
본문 바로가기
워게임/pwnable.kr

[pwnble.kr] leg

728x90

1. 문제


1) 문제 확인 

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

leg.c와 leg.asm을 준다. 소스코드를 보면 key 1,2,3 함수의 반환값을 입력값과 맞춰야 한다. arm 환경에서 작성된 코드이므로 arm 로직 이해가 약간 필요하다. 

 

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.
(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.
(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.
(gdb)

 

위 로직을 분석하여 key 1,2,3 함수의 반환값이 무엇인지 파악한뒤 그거에 맞게 입력값을 주면 될것이다. 

 

2. 접근방법


(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.

r0에 함수의 반환값이 담기므로 mov r3, pc ; 를 보면 된다. pc에서는 0x00008ce4 가 담기므로 key 1의 반환값은 0x00008ce4이다. 

 

(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	l

key2에서는 pc를 r3에 넣고, +4 를 한뒤에 r0에 넣는다. 즉 0x8d0c가 r0에 담긴다. 

 

(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이 r0에 담긴다. 따라서 key3함수가 끝나고 실행될 주소인, 0x00008d80 가 반환값이다. 

 

3. 풀이


 

  1. 0x00008ce4
  1. 0x8d0c
  1. 0x00008d80

 

3개를 더한값으로 입력값을 주면 된다. 

 

 

 

4. 몰랐던 개념


CPU 명령 사이클
명령어가 하나 수행되기 까지의 기본적인 3단계를 거친다. Fetch : CPU가 기억장치로부터 명령어를 읽어옴 Decode : 읽어온 명령어를 CPU가 이해할수 있도록 기계어로 번역 Execute : 명령어 실행 CPU 내부 구조는 다음과 같다. 출처 : https://m.blog.naver.com/PostView.nhn?blogId=wooin0707&logNo=221591419262&proxyReferer=https:%2F%2Fww 명령어가 한사이클을 돌때마다 위 사진 내부에서 fetch ⇒ decode ⇒ execute 가 실행된다.
https://wogh8732.tistory.com/275

 

728x90

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

[pwnable.kr] md5 calculator  (0) 2020.09.23
[pwnable.kr] brainfuck  (0) 2020.09.23
[pwnable.kr] shellshock  (0) 2020.09.06
[pwnable.kr] mistake  (0) 2020.09.06
[pwnable.kr] input  (0) 2020.09.06