본문 바로가기

포너블

(9)
드림핵 ssp_000 롸업 #include #include #include #include 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(30); } void get_shell() { system("/bin/sh"); } int main(int argc, char *argv[]) { long addr; long value; char buf[0x40] = {}; initialize(); read(0, buf, 0x80); printf("Addr : "); scanf..
드림핵 ssp_001 롸업 #include #include #include #include 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(30); } void get_shell() { system("/bin/sh"); } void print_box(unsigned char *box, int idx) { printf("Element of index %d is : %02x\n", idx, box[idx]); } void menu() { puts("[F]ill the ..
Stack Canary & Return to Shellcode 롸업 스택 카나리는 스택 버퍼 오버플로우로부터 반환 주소 ret를 보호하는 기법이다. 이렇게 버퍼와 ret 사이에 임의의 값을 삽입해서 해당 값의 변조가 확인되면 프로세스를 종료시키는 보호 기법이다. 카나리는 TLS(Thread Local Storage)에 저장되기 때문에 TLS의 주소를 알고 값을 읽으면 카나리 검사를 우회가능하다. 리눅스에서 카나리를 저장하는 주소는 fs+0x28이다. #include #include int main() { char buf[0x50]; printf("Address of the buf: %p\n", buf); printf("Distance between buf and $rbp: %ld\n", (char*)__builtin_frame_address(0) - buf); print..
드림핵 basic_exploitation_001 롸업 #include #include #include #include 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(30); } void read_flag() { system("cat /flag"); } int main(int argc, char *argv[]) { char buf[0x80]; initialize(); gets(buf); return 0; } 문제 코드이다. buf의 크기는 0x80인데 gets로 입력을 받을 때 크기를 지정하..
드림핵 basic_exploitation_000 롸업 #include #include #include #include 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(30); } int main(int argc, char *argv[]) { char buf[0x80]; initialize(); printf("buf = (%p)\n", buf); scanf("%141s", buf); return 0; } 문제 코드이다. 버퍼의 크기가 128바이트인데 scanf에서 141바이트까지 입력을 받을 ..
Stack Buffer Overflow & Return Address Overwrite 롸업 x86-64호출 규약 SYSV는 6개의 인자를 RDI, RSI, RDX, RCX, R8, R9에 순서대로 저장하여 전달한다. 더 많은 인자를 사용할 때는 스택을 추가로 이용한다. 함수의 반환 값은 RAX로 전달한다. x86 호출 규약 cdecl은 스택을 통해 인자를 전달한다. 스택 버퍼 오버플로우는 스택에 있는 버퍼의 크기보다 큰 값을 담으려고 할 때 오버플로우가 발생하는 취약점이다. 오버플로우로 인해 버퍼 뒤에 있는 스택 값을 조작해 해킹에 이용할 수 있다. 스택 구조를 파악하면 오버플로우로 반환 주소를 바꾸거나 뒤에 있는 값을 읽어오는 등 많은 작업을 할 수 있다. 개념 자체는 간단한 기법이라 더 설명할게 없는데 너무 짧으니 드림핵 함께실습에 있는 문제의 풀이까지 같이 작성해보겠다. #include ..
드림핵 shell_basic 롸업 입력한 셸코드를 실행하는 프로그램이 서비스로 등록되어 작동하고 있습니다. main 함수가 아닌 다른 함수들은 execve, execveat 시스템 콜을 사용하지 못하도록 하며, 풀이와 관련이 없는 함수입니다. flag 파일의 위치와 이름은 /home/shell_basic/flag_name_is_loooooong입니다. 감 잡기 어려우신 분들은 아래 코드를 가지고 먼저 연습해보세요! __asm__( ".global run_sh\n" "run_sh:\n" "push 0x0\n" "mov rax, 0x676e6f6f6f6f6f6f\n" "push rax\n" "mov rax, 0x6c5f73695f656d61\n" "push rax\n" "mov rax, 0x6e5f67616c662f63\n" "push ra..
범용 레지스터 & gdb(pwndbg) & pwntools 자주 사용되는 범용 레지스터를 알아야 셸 코드를 짤 수 있는데 계속 까먹어서 따로 정리한다. gdb 역시 코드 분석에 필요한데 사용법, 명령어가 아직은 헷갈려서 정리한다. 리눅스의 실행파일 형식은 ELF인데 ELF의 헤더에는 실행에 필요한 여러 정보가 있다. readelf -h 파일이름 으로 진입점, entry point를 확인할 수 있다. 그냥 gdb에서 entry 라고 치면 진입점부터 분석할 수 있다. 브레이크는 b *main 이런식으로 하고 run은 그냥 r 하나만 치면 된다. b: break c: continue r: run si: step into ni: next instruction i: info k: kill pd: pdisas 이런 명령어들이 있다. disassemble main 이런식으로..