[LOB] darkknight -> bugbear

Posted by dw0rdptr
2015. 4. 12. 15:30 System/LOB


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
        The Lord of the BOF : The Fellowship of the BOF
        - bugbear
        - RTL1
*/
 
#include <stdio.h>
#include <stdlib.h>
main(int argc, char *argv[])
{    
    char buffer[40];    
    int i;    
    
    if(argc < 2){        
        printf("argv error\n");       
        exit(0);    
    }    
 
    if(argv[1][47== '\xbf')    
    {        
        printf("stack betrayed you!!\n");        
        exit(0);    
    }    
    
    strcpy(buffer, argv[1]); 
    printf("%s\n", buffer);
 
}
cs


bugbear의 소스이다 . 힌트를 보면 알 수 있듯이 이번엔 RTL 기법을 사용해서 풀어야 한다. ret에 스택내의 주소를 덮으려하면 스택이 배신했다고 하면서 종료돼버린다.


RTL(Return To Libc) : 스택에서 어떤 코드도 실행되지 못하도록 하는 보호기법이 나온 이후 나온 기법. 프로그램이 실행될 때 프로그램이 사용한 함수를 포함한 내장라이브러리인 Libc가 Libc 영역에 적재된다. 이 라이브러리에는 system()함수도 포함되어있는데 프로그램이 이함수를 쓰지 않더라도 LIbc가 통째로 올라가기 때문에 메모리에 같이 적재된다

*system()함수 : 명령어를 실행하는 함수. 


이제 메모리 적재되어있는 Libc 영역에서 system() 함수의 주소를 찾고 인자로 "/bin/sh"를 주면 다음레벨의 쉘을 딸 수 있을것이다.


system()함수의 주소는0x40058ae0이다.


이제 "/bin/sh"문자열이 있는 주소를 전달하면 되는데 환경변수를 /bin/sh로 등록해도되지만 system() 함수 내에서도 /bin/sh라는 문자열이 존재한다.

1
2
3
4
5
6
7
8
9
10
int main(int argc, char * argv[])
{
    long shell;
    shell = 0x40058ae0//system 함수 주소
    while(memcmp((void *)shell, "/bin/sh"8)) //시스템 함수 내에서 /bin/sh문자열 비교 
    shell++;
    printf("/bin/sh = %p\n",shell); // /bin/sh문자열이 있는 
}
 
 
cs

 위 소스로 "/bin/sh" 문자열이 있는 주소를 찾을 수 있다.


주소는 0x400fbff9


프로그램의 ret주소를 system()함수의 주소로 채우고 뒤에 인자를 전달하는데, ret명령에 의해 호출된 system() 함수는 ret가 쌓이지 않기 때문에 비어있는 ret자리인 4byte를 더미로 채우고 인자(/bin/sh의 주소)를 전달한다



페이로드와 Password




'System > LOB' 카테고리의 다른 글

[LOB] giant -> assassin  (0) 2015.04.14
[LOB] bugbear -> giant  (2) 2015.04.14
[LOB] golem -> darkknight  (0) 2015.04.11
함수의 프롤로그(prologue) 및 에필로그(epilogue)  (0) 2015.04.10
[LOB] skeleton -> golem  (0) 2015.04.07

[LOB] golem -> darkknight

Posted by dw0rdptr
2015. 4. 11. 02:16 System/LOB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkknight
        - FPO
*/
 
#include <stdio.h>
#include <stdlib.h>
 
void problem_child(char *src)
{
    char buffer[40];
    strncpy(buffer, src, 41);
    printf("%s\n", buffer);
}
 
main(int argc, char *argv[])
{
    if(argc<2){
        printf("argv error\n");
        exit(0);
    }
 
    problem_child(argv[1]);
}
cs


먼저 함수의 프롤로그와 에필로그 글을 보고 오자


darkknight 소스를 보면
주석에 FPO라고 쓰여져있는데 이는 Frame Pointer Overflow의 약자로 함수 에필로그 과정에서 함수를 종료하면서 ebp포인터를 복구시킬 때 공격자가 원하는곳으로 ebp를 이동시켜 공격코드를 실행시키는 기법이다.


strncpy함수를 쓰는데 41바이트제한으로 딱 1바이트 오버플로우를 시킬 수 있다. sfp(saved frame pointer) 영역의 마지막 1바이트를 변조시킬 수 있다. 겨우 1바이트로 뭘하지 할텐데

우선 sfp에 저장되어있는 값을 보자

버퍼크기만큼 채운 NOP바로 뒤 sfp에 0xbffffa00값이 들어있다.

버퍼의 시작주소가 담겨있는 주소 역시 0xbffffaa0로 앞의 3바이트가 같으므로 1바이트 변조로도 ebp를 버퍼로 이동시킬 수 있다.


? 세폴이 뜬다. core를 떨어트려 분석해보자


역시 주소가 바뀌어있다. 80으로 바꿔서 해보자


세폴이뜬다.

problem_child에서 sfp를 변조하면 ebp는 0xbffffa80으로 날아간다. 그리고 main으로 돌아가서 나머지들을 실행한 후

main의 leave 과정을 통해 mov esp, ebp 명령어를 실행 할 때 esp가 0xbffffa80으로 날아가게 된다

leave과정중 pop ebp를 하게 되면 esp값이 +4가 된다.

그상태에서 ret과정을 통해 pop eip와 jmp eip, 결과적으로 0xbffffa80(esp)+4의 주소에 있는 값이 eip에 들어가고 그 값으로 jmp(점프)하게 되어서 0x90909090 주소로 점프해버려 쉘코드 실행이 되지 않는것이다,


주소를 -4하면 해결된다

\x80->\x7c


페이로드와  Password







'System > LOB' 카테고리의 다른 글

[LOB] bugbear -> giant  (2) 2015.04.14
[LOB] darkknight -> bugbear  (0) 2015.04.12
함수의 프롤로그(prologue) 및 에필로그(epilogue)  (0) 2015.04.10
[LOB] skeleton -> golem  (0) 2015.04.07
[LOB] vampire -> skeleton  (0) 2015.04.01

함수의 프롤로그(prologue) 및 에필로그(epilogue)

Posted by dw0rdptr
2015. 4. 10. 03:51 System/LOB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkknight
        - FPO
*/
 
#include <stdio.h>
#include <stdlib.h>
 
void problem_child(char *src)
{
    char buffer[40];
    strncpy(buffer, src, 41);
    printf("%s\n", buffer);
}
 
main(int argc, char *argv[])
{
    if(argc<2){
        printf("argv error\n");
        exit(0);
    }
 
    problem_child(argv[1]);
}
cs

r

LOB darkknight의 소스이다. strncpy함수를 호출하는데 딱 1바이트만 오버플로우를 일으킬 수 있다.

이문제는 FPO(Frame Pointer Overflow)기법으로 풀어야 하는데 그전에 함수 프롤로그와 에필로그를 먼저 이해해야 한다.



참고) mov %esp(source),%ebp(destination)   -> AT&T 문법

  mov ebp(destination), esp(source)        -> intel 문법       

둘은 같은 명령을 의미(표기방법의 차이. 자세한건 구글신)


main에서 p(problem_child)함수를 호출했다.

어셈블리에선 생략되어있지만 우선 ret이 생성된다.

higher address

------------

      ret

------------ <-esp

lower address



먼저 push %ebp를 한다. 현재 ebp에는 main함수의 frame pointer(base pointer라고도 함)값이 있는데 이를 push해서 저장한 공간을 sfp(saved frame pointer) 라고 한다. push하였기 때문에 esp가 움직인다.

higher address

------------

      ret

------------

sfp(main의 ebp)

------------ <- esp

lower address



그리고 mov %esp, %ebp로 현재의 esp값을 ebp에 넣는다.(ebp를 esp로 이동시킨다)

현재까지의 스택상황을 보면

higher address

------------

      ret

------------

sfp

------------ <- ebp,esp

lower address


지금 ebp의 위치가 p함수의 frame pointer가 되는것이다

여기까지가 함수 프롤로그.



이제 p함수내에서 버퍼를 선언하면

higher address

------------

      ret

------------

sfp

------------ <- ebp


  buffer[40]

------------ <- esp

lower address


이렇게 esp에서 할당할 만큼의 공간을 빼면서 진행한다




* 아무래도 intel문법이 편해서 지금부턴 intel문법을 쓰겠다.




함수에필로그 과정은  leave와 ret이 있다

각각의 부분에서 실행하는 명령어는 다음과 같다

leave

ret

mov esp, ebp

 pop eip

pop ebp

 jmp eip


먼저 leave에서 p함수는 mov esp, ebp로 그동안 함수내에서 진행한 esp를 ebp값으로 돌려놓는다, 즉 위에서 진행했던 p함수의 프롤로그가 진행된 직후 상태로 되돌린다.

higher address

------------

      ret

------------

sfp

------------ <- ebp,esp

lower address




그리고 pop ebp명령어를 통해 sfp에 들어있던 main의 frame pointer 값이 ebp로 들어가게 된다 (ebp는 이제 main의 frame pointer를 가리키게 됨) pop했으니 esp 4증가.

higher address

------------

      ret

------------ <- esp

lower address



마지막으로 pop eip를 하면 ret에 있는 주소가 eip에 들어가게되고 jmp eip로 점프해 main함수 안의 p함수를 호출한 직후로 가게된다.





darkknight의 풀이는 다음글에서 다룰것이다. 이 글을 이해했으면 굳이 다음 글을 읽지 않아도 해결할 수 있을 것이다.



'System > LOB' 카테고리의 다른 글

[LOB] darkknight -> bugbear  (0) 2015.04.12
[LOB] golem -> darkknight  (0) 2015.04.11
[LOB] skeleton -> golem  (0) 2015.04.07
[LOB] vampire -> skeleton  (0) 2015.04.01
[LOB] troll -> vampire  (0) 2015.04.01