mips에서도 bof가 발생할 경우 rop가 가능하다. 하지만 x64 rop와 큰 차이점이 2가지 있다. 첫 번째로x64 rop는 pop rdi; ret ; pop rsi; pop rdx ; ret 뭐 이런식으로 rsp 가 움직이면서 인자 값을 레지스터에 딱 딱 넣는다. 그러나 mips의 레지스터에 값을 저장하는 방식은 sp를 기준으로 n만큼 떨어진 주소의 값을 가져오는 방식을 사용한다.즉, sp는 가만히 있고 a0 = [sp+0x10] , a1 = [sp+0x20] 이렇게 인자를 가져오기 때문에 가젯을 구하는게 상당히 힘들다.예를 들어서 가젯을 구했는데 a0의 값도 sp+0x10 에서 가져오고 a1의 값도 sp+0x10에서 가져온다면 두 가젯중 하나만 사용 가능해진다. 또한 깔끔한 가젯이 없기 때문에..
execve("/bin/sh",0,0) 를 실행하는 main 함수의 어셈블리 코드는 다음과 같다.mips도 execve 함수 내부에서 syscall 이 이루어진다.x64에서는 syscall이 호출되었을 때 rax 값에 따라 어떤 작업을 수행할 지 결정되는데 misp는 해당 역할을 v0이 수행한다. 인자 순서는 a0, a1, a2 순서이다.syscall 직전에 레지스터 값을 확인해보자.v0 : 0xfaba0 : "/bin/sh" 주소a1 : 0a2 : 0 이제 쉘코드를 만들어 보자. 다음과 같이 어셈블리코드를 짤 수 있다..section .text .globl _start_start: li $t0, 0x2f62696e sw $t0, ($sp) li $t0, 0x2f2f7368 s..
mips 란?Microprocessor without Interlocked Pipelined Stages 아키텍처 중 하나로 4byte 주소체계를 가진 RISC 기반 명령어이다.mips의 특징중에는 특이한 것이 하나 있는데 바로 "delay slot" 이라는 것을 사용한다.이는 branch 나 jump같은 분기 명령이 실행될 때 다음 줄 명령까지 실행한다는 것이다. 그렇기 때문에 rop 를 짤때 마지막 한 줄을 생각해줘야 한다.예를 들어서 다음 코드를 보자.1) lw gp,24(s8)2) li a0,13) lw v0,-32584(gp)4) move t9,v05) jalr t96) nop다음과 같은 어셈블리 코드가 실행이 된다고 치자. 원래같으면 1, 2, 3, 4, ..
file stream oriented programming _IO_FILE 이란? 리눅스 시스템의 표준 라이브러리에서 파일 스트림을 나타내기 위한 구조체, fopen(), fwrite(), fclose() 등 파일 스트림을 사용하는 함수가 호출되었을때 할당 구조체 struct _IO_FILE { int _flags;/* High-order word is _IO_MAGIC; rest is flags. */ /* The following pointers correspond to the C++ streambuf protocol. */ char *_IO_read_ptr;/* Current read pointer */ char *_IO_read_end;/* End of get area. */ char *_IO_r..
이는 exit함수로 종료될 경우에 Full RELRO 보호기법이 적용되어있을 때 사용 가능한 공격이다. Full RELRO 보호기법이 적용되어 있기 때문에 .fini_array overwrite는 사용할 수 없다. 우선 main이 종료되는 과정을 보자. main이 종료되는 과정 main 함수가 리턴된 후, exit 함수를 호출한다. 여기서 인자값이 0인것을 알 수 있는데 이는 흔히 c언어에서 main의 마지막에 return 0 ; 를 하는데 이 0이 exit함수의 파라미터로 들어가 것이다. exit함수 내부에서는 __run_exit_handlers를 호출한다. 계속 따라가다 보면 _dl_fini를 호출한다. __run_exit_handlers 함수는 exit_function 구조체 멤버 변수인 flavo..
stack address leak libc_base를 알고있을 때 stack_address 를 알아낼 수 있는 기법이다. 라이브러리에서는 프로그램의 환경 변수를 참조해야 할 일이 있다. 이를 위해 libc.so.6에는 environ 포인터가 존재하고, 이는 프로그램의 환경 변수를 가리키고 있다. environ 포인터는 로더의 초기화 함수에 의해 초기화된다. environ 변수의 오프셋 구하는 법 objdump -D /lib/x86_64-linux-gnu/libc.so.6 | grep "environ" environ에 stack 주소가 있는 것을 알 수 있다. 예제 //gcc -zexecstack -no-pie -o enp enp.c #include #include #include long int buf_..
stack pivoting이란? ROP를 하고 싶은데 BOF가 ret까지만 덮을수 있을경우(overflow가 많이 나지 않은 경우)혹은 main으로 돌아갈 수 없는 경우에 하는 방법이다 공격방법 gadget을 이용해서 쓰기 가능한 공간에 Fake Stack을 구성해놓고 chaining하는 기법이다. 특정 영역에 값이 있거나 값을 쓸수 있을경우 SFP를 이용하여 스택을 옮기고 해당 부분의 코드를 실행한다. 즉 어떤 공간을 스택처럼 사용하는 것이다. 예를 들면 sfp에 bss주소를 넣고 read등의 함수를 사용한다. 그리고 leave_ret 가젯을 통해 rbp를 bss로 보내 bss를 스택처럼 사용한다. 그리고 ret으로 그 이후의 명령어들을 실행시킨다 예제 //gcc -o pivot pivot.c -fno..