본문 바로가기

project/MIPS(EL) 32bit analysis

2. 프로그램 분석

스터디의 목표가 임베디드에 대한 어플리케이션 레벨에 대한 공격인 만큼, 

원래 간단한 바이너리 부터 흐름을 천천히 분석 해 보면서, 

변수선언 / 값 대입 / 함수호출 / 다양한 데이터형   에 관한 주제로 분석을 해 볼려고 했지만, 진도를 좀더 빠르게 빼기 위해서 실제 bof취약점이 있는 코드를 컴파일 해서 분석 해 보기로 하였다. 

예제코드는 다음과 같다.


/****************************

  leaveret embedded study

  disable NX

  Make shellcode and attack!

*****************************/

#include <stdio.h>

#include <string.h>


int main(int argc,char *argv[])

{

char buf[100];

strcpy(buf,argv[1]);

printf("%s\n",buf);

return 0;

}



gdb로 디스어셈한 창을 보면,


와 같이 보이는데, 사실 처음엔 아무것도 안보였다. 다만 RISC형식이라는 것을 4바이트씩 증가하는 주소값을 보고 알 수 있었다.


차례대로 분석 해보자면,

   0x00400670 <+0>: addiu  sp,sp,-136     // sp = sp - 136

   0x00400674 <+4>: sw ra,132(sp)       //  Memory[sp+132] = ra

   0x00400678 <+8>: sw s8,128(sp)       //  Memory[sp+128] = s8

   0x0040067c <+12>: move s8,sp               //  s8 = sp

위 네줄은 intel x86의 프롤로그와 흡사하다.

sp는 스택포인터를 뜻하며, ra는 리턴어드레스를 가지고 있는 레지스터이고, s8은 ebp, 즉 스택 프레임의 기준이 되는 base pointer의 역할을 한다.


   0x400680 <main+16>: sw a0,136(s8)    // Memory[s8+136] = a0

main 함수의 첫번째 인자, argc를 지역변수 공간에 저장

   0x400684 <main+20>: sw a1,140(s8)    // Memory[s8+140] = a1

main함수의 두번째 인자, argv를 지역변수 공간에 저장


   0x400688 <main+24>: lw v0,140(s8)     // v0 = Memory[s8+140]

   0x40068c <main+28>: addiu  v0,v0,4        // v0 = v0 + 4

   0x400690 <main+32>: lw v0,0(v0)        // v0 = Memory[v0]    //argv[1]

v0에 argv[1]의 주소를 가져오는 과정


   0x400694 <main+36>: addiu  v1,s8,24        // v1 = s8+24            //buf

v1에 buf주소를 가져오는 과정


   0x400698 <main+40>: move a0,v1            //  a0 = v1

   0x40069c <main+44>: move a1,v0            //  a1 = v0

strcpy의 인자를 주기위해 a0, a1를 셋팅


   0x4006a0 <main+48>: jal 0x400520 <strcpy@plt>    //  ra = PC+4, PC = 0x400520

   0x4006a4 <main+52>: move at,at                        //   at  =  at     // I don't know

jal은 call과 똑같음,  원래대로라면 주석처럼 값이 들어가야겟지만, si로 따라 들어가서 ra를 확인해본 결과 ra = PC+8의 주소가 들어같다. move at,at을 왜 해주는지 이해가 가지 않지만, 찾아도 잘 안나오길래 넘어갔다. 단순히 NOP likely라서 그런가 했다.


검색을 조금 해보니, 이건 파이프라인 프로세서에서 나타나는 특징중에 하나인데, 딜레이 슬롯 이라고 해서 분기가 실행될 시점에서 분기 명령 다음에 있는 명령은 이미 파이프라인 안에 들어와있기 때문에 NOP likely한 명령으로 채운다, 근데 at레지스터의 기능을 보면, 

$at Register[edit]

The $at (Assembler Temporary) register is used for temporary values within pseudo commands. It is not preserved across function calls. For example, with the (slt $at, $a0, $s2) command, $at is set to one if $a0 is less than $t2, otherwise it is set to zero.

수도커맨드 사이에서 임시저장용으로만 쓰이고 함수호출에서는 값이 유지되지 않는다.라는 식으로 해석 할 수 있을꺼 같다.

이와 같이 wiki에 설명되어있는데, 자세한것은 모르겟지만,  저 명령으로 나머지 파이프라인을 채워 줄 수 있는 것 같다.


   0x4006a8 <main+56>: addiu v0,s8,24                   // v0 = s8 + 24     //buf

   0x4006ac <main+60>: move a0,v0                        // a0 = v0

   0x4006b0 <main+64>: jal 0x400530 <puts@plt>    //  call puts

   0x4006b4 <main+68>: move at,at

puts를 부르는 과정이다.


   0x004006b8 <+72>: move v0,zero

v0(리턴값)을 0으로 한다.   return 0;로 하는거 같다.


   0x004006bc <+76>: move sp,s8

   0x004006c0 <+80>: lw ra,132(sp)

   0x004006c4 <+84>: lw s8,128(sp)

   0x004006c8 <+88>: addiu sp,sp,136

에필로그이다. 지역변수 공간에 저장된 ret과 frame pointer를 다시 ra와 s8에 저장한다.

그리고 sp를 다시 되돌린다.


   0x004006cc <+92>: jr ra

   0x004006d0 <+96>: move at,at

ret이다.




주의해야 될 점은 MIPS는 RISC라서   PC조정할때 4의 배수 아니면 세그폴트가 일어난다는 점이였다.





그리고, 

root@debian-mipsel:~/leaveret# cat > test1.c

#include <stdio.h>

int main()

{

int a=1;

int b=0;

b=a; 

return 0;

}


(gdb) disas main

Dump of assembler code for function main:

   0x004005c0 <+0>: addiu sp,sp,-24

   0x004005c4 <+4>: sw s8,20(sp)

   0x004005c8 <+8>: move s8,sp

   0x004005cc <+12>: li v0,1

   0x004005d0 <+16>: sw v0,8(s8)

   0x004005d4 <+20>: sw zero,12(s8)

   0x004005d8 <+24>: lw v0,8(s8)

   0x004005dc <+28>: sw v0,12(s8)

   0x004005e0 <+32>: move v0,zero

   0x004005e4 <+36>: move sp,s8

   0x004005e8 <+40>: lw s8,20(sp)

   0x004005ec <+44>: addiu sp,sp,24

   0x004005f0 <+48>: jr ra

   0x004005f4 <+52>: move at,at


다음과 같이 함수에서 서브함수를 호출하지않는 프로그램이 있다고 했을때, 

ra가 현재 스택프레임에 저장되지 않음으로, overflow가 일어나도 ra를 컨트롤 할 방법이 없다.


'project > MIPS(EL) 32bit analysis' 카테고리의 다른 글

5. RTL공격  (0) 2015.01.21
4. 쉘코드를 이용한 간단한 BOF공격  (0) 2015.01.19
3. 쉘코드 제작  (0) 2015.01.19
1. 환경구성  (3) 2015.01.19