
매우 빠른™ 멀티스레드 ROP 가젯 파인더. ropper / ropgadget 대안 (현재 x86 전용)
ropr는 매우 빠른 멀티스레드 ROP Gadget 찾기 도구입니다.
ROP (Return Oriented Programming) Gadgets는 각 바이너리나 라이브러리에 이미 실행 가능한 코드로 존재하는, 일반적으로 ret 명령어로 끝나는 몇 개의 어셈블리 명령어로 구성된 작은 코드 조각입니다. 이러한 Gadgets는 바이너리 익스플로잇과 취약한 실행 파일을 공격하는 데 사용될 수 있습니다.
많은 ROP Gadgets의 주소가 버퍼에 기록되면 ROP Chain이 형성됩니다. 공격자가 스택 포인터를 이 ROP Chain으로 이동시킬 수 있다면 제어권을 완전히 공격자에게 넘길 수 있습니다.
대부분의 실행 파일에는 튜링 완전한 ROP Chain을 작성할 수 있을 만큼 충분한 Gadgets가 포함되어 있습니다. 그렇지 않은 경우, 주소를 알고 있다면 libc와 같이 동일한 주소 공간에 포함된 동적 라이브러리를 사용할 수 있습니다.
ROP Gadgets를 사용하는 장점은 어디에도 새로운 실행 코드를 작성할 필요가 없다는 것입니다. 공격자는 프로그램에 이미 존재하는 코드만으로도 목표를 달성할 수 있습니다.
일반적으로 ROP Gadgets를 사용하기 위한 첫 번째 요구 사항은 ROP Chain을 기록할 공간을 확보하는 것입니다. 이는 읽기 가능한 버퍼라면 무엇이든 될 수 있습니다. 사용하려는 각 Gadget의 주소를 이 버퍼에 기록하기만 하면 됩니다. 버퍼가 너무 작으면 긴 ROP Chain을 기록할 공간이 충분하지 않을 수 있으므로, 공격자는 사용 가능한 공간에 맞게 ROP Chain을 효율적으로 구성해야 합니다.
두 번째 요구 사항은 스택을 제어할 수 있어야 한다는 것입니다. 이는 스택 오버플로우의 형태로 나타날 수 있습니다. 스택 오버플로우를 통해 ROP Chain을 스택 포인터 아래에 직접 기록할 수 있습니다. 또는 "스택 피벗"이라는 단일 Gadget을 사용하여 스택 포인터를 나머지 ROP Chain으로 이동시킬 수도 있습니다.
스택 포인터가 ROP Chain의 시작 부분에 위치하면, 다음 ret 명령어가 순서대로 Gadgets를 실행하게 됩니다. 각 Gadget은 다음 Gadget을 자신의 스택 프레임에 대한 반환 주소로 사용합니다.
함수 포인터를 ROP Chain에 추가하는 것도 가능합니다. 이 경우 함수 인수는 ROP Chain의 다음 요소 뒤에 제공되어야 합니다. 이는 일반적으로 "pop gadget"과 결합되어, 함수 인수 뒤의 다음 Gadget으로 원활하게 전환하기 위해 인수를 스택에서 꺼냅니다.
간편 설치:
cargo install ropr
애플리케이션은 ~/.cargo/bin에 설치됩니다.
소스에서 설치:
git clone https://github.com/Ben-Lichtman/ropr
cd ropr
cargo build --release
결과 바이너리는 target/release/ropr에 위치합니다.
또는:
git clone https://github.com/Ben-Lichtman/ropr
cd ropr
cargo install --path .
애플리케이션은 ~/.cargo/bin에 설치됩니다.
USAGE:
ropr [OPTIONS] <BINARY>
ARGS:
<BINARY> The path of the file to inspect
OPTIONS:
-b, --base-pivot Filters for gadgets which alter the base pointer
-c, --colour <COLOUR> Forces output to be in colour or plain text (`true` or `false`)
-h, --help Print help information
-j, --nojop Removes "JOP Gadgets" - these may have a controllable branch,
call, etc. instead of a simple `ret` at the end
-m, --max-instr <MAX_INSTR> Maximum number of instructions in a gadget [default: 6]
-n, --noisy Includes potentially low-quality gadgets such as prefixes,
conditional branches, and near branches (will find significantly
more gadgets)
-p, --stack-pivot Filters for gadgets which alter the stack pointer
-r, --norop Removes normal "ROP Gadgets"
-R, --regex <REGEX> Perform a regex search on the returned gadgets for easy filtering
--range <RANGE> Search between address ranges (in hexadecial) eg. `0x1234-0x4567`
--raw <RAW> Treats the input file as a blob of code (`true` or `false`)
-s, --nosys Removes syscalls and other interrupts
-V, --version Print version information
예를 들어, 다른 레지스터의 값으로 rax를 채울 방법을 찾고 있다면 정규식 ^mov eax, ...;으로 필터링할 수 있습니다:
❯ ropr /usr/lib/libc.so.6 -R "^mov eax, ...;" > /dev/null
==> Found 197 gadgets in 0.118 seconds
이제 가장 높은 품질의 결과를 위해 명령줄에 몇 가지 필터를 추가할 수 있습니다:
❯ ropr /usr/lib/libc.so.6 -m 2 -j -s -R "^mov eax, ...;"
0x000353e7: mov eax, eax; ret;
0x000788c8: mov eax, ecx; ret;
0x00052252: mov eax, edi; ret;
0x0003ae43: mov eax, edx; ret;
0x000353e6: mov eax, r8d; ret;
0x000788c7: mov eax, r9d; ret;
==> Found 6 gadgets in 0.046 seconds
이제 주소 0x00052252에 좋은 mov gadet 후보가 있습니다.