CIDY
[MHSCTF 2023] Feb. 5 — Rescue Mission 본문
흠.. 이런 게임 형식 문제는 둘중 하나다. 싸워 이기는건 둘째치고 취약점 찾아서 쉘따기 or 싸워 이기면 알아서 플래그 줌.
얘는 후자인듯.
일단 오픈소스라 맘은 편하다.
clear()함수. 도대체 뭘 출력하고 싶은건지.. 저번에 NVODIA풀때도 이런 게 있었는데 오늘 그 의문을 해결했다.
https://stackoverflow.com/questions/66927511/what-does-e-do-what-does-e11h-e2j-do
직접 실행하고 입력 몇번 해봐도 알 수 있다.
요런 식으로 스크롤 위치를 딱 맞춰서 이동시켜주는 기능이고, 실질적으로 뭐 출력해주는 건 없다. (한마디로 신경 안 써도 됨.)
크게 doBattle함수와 doShop함수가 존재한다. 그렇지만 main먼저 보기로 하자.
엔터치래서 치면 시작된다.
3회동안 shop과 battle을 거쳐 최종 보스랑 싸우는듯.
머니를 비롯한 초기 설정은 위와 같다.
doShop함수 먼저 보자.
들어가면 이렇게 현재 자산을 알려준 뒤, 네 가지 선택지를 준다. 0입력하면 바로 doShop은 return된다.
1을 입력할 경우
위와 같이 현재 돈을 보여주고, 살 수 있는 선택지를 보여준다.
선택을 하고 나면 Quantity? 라고 물음. 선택한 품목을 몇 개살거냐는 얘기인듯.
%s로 입력받아서 atoi함. %s...아 이거 바이너리라도 있었으면 바로 IDA돌려서 변수 위치 확인하는건데.. 이변없이 선언 순서대로 쌓인다고 가정해도 할 수 있는 많다. 이게 내가 아주 조작해서 쉘 따야하는게 아니니까 (애초에 바이너리가 없어서 checksec같은것도 안 됨 ㅋㅋ) 그냥 변수 몇개만 조작해서 게임을 이길 수 있도록만 하면 된다.
doShop내에서 선언 순서는
int done
int selection
char quantity[20]
int price
int buff
int qint
흠 그럼 해봤자 done이랑 selection조작할 수 있는거 아닌가? 일단 ㅇㅋ
암튼 입력받은 퀀티티를 atoi돌림. 그리고 음수일 경우 강제적으로 양수로 만든다.
이런 식으로.. 그리고 가격 출력하고 가격이 내 돈보다 클 경우 부족하다고 알림뜨고 다시 품목 고르는 곳으로 돌아가겠지. 그게 아니면 내 돈에서 가격 빼고 player.health를 올린다.
아 그리고 품목 고를때 이상한거 고르면 price buff모두 0이라 0원으로 결제되고 효과 없음.
이건 attack상승임. 과정은 비슷한데 단일품목이라 가격이랑 버프가 고정이고 나는 퀀티티만 입력하면 됨. 역시 음수일 경우 양수로 변경하고.. 나머지 과정은 같음.
머 이런 식이고 아예 품목 선택 입력을 안 받음. 이것 역시 quantity를 %s로 입력받아서 취약하긴 한데,, 변수 순서상 뭐 크게 할 수 있는게 있나 싶다.
마지막 품목이다.
얘도 역시 단일. 우선순위를 낮춰주는데 얘가 무슨 역할을 하는지는 배틀가봐야 할듯. 구매과정은 모두 같음.
그렇게 doShop하고나면(doShop은 인자 받지도 않는데 왜 전달한건지 모르겠네) 적의 스펙을 랜덤하게 결정한다. %연산 하는거보면 꽤나 현실적인 수치로 주는듯.
그럼 doBattle보러가자.
가장 먼저 누가 첫 턴을 가져갈지 결정한다. 우선순위가 더 작은 쪽이 먼저 공격권을 가져간다.
뭐 이런 식으로..
이건 내 턴이 먼저일때다. 일단 시작하면 나와 적의 스펙을 쭉 보여준다.
그런 다음 1에서 내 attack사이 숫자를 고를 수 있다. 그걸 pnum에 입력하면 되는데 범위 밖 숫자를 고르는 게 막혀져 있지는 않음.
anum은 랜덤하게 결정되는데, 내 attack으로 %한거에 + 1하는거라서 [1] ~ [최대 내 attack]의 값이 나올 수 있다. pnum과 anum이 동일하면 공격이 블락되는데, 범위 밖 숫자를 제한없이 고를 수 있으니 블락을 무조건 회피할 수 있다;;
블락되지 않고 히트가 정상적으로 들어갔을 경우, 데미지는 위와 같이 [내 공격 * 2] ~ [내 공격 * 4 - 1]의 값 사이에서 랜덤하게 결정된다. 그리고 health[1]은 enemy의 health를 저장해둔건데, 거기서 데미지만큼 뺌.
이건 상대 턴일 때다. 역시 나와 상대 스펙을 순서대로 쭉 보여준다. 그리고 1 - 상대 attack 중 숫자를 선택하라고 함. 그게 pnum이고, anum은 1 - 상대 attack중 랜덤하게 결정. 이건 내가 블락해야 유리한 상황이니 범위에 맞게 숫자를 입력해주는게 좋겠다. pnum이 anum과 동일하고, 상대 체력이 보스 체력과 달라야 공격이 블락된다.
그게 아닐 경우 아까와 같은 방식으로(이번엔 상대 체력 기준) 데미지가 결정되고, health[0]에서 까임. 전역에서 까이는게 아니라 다행인가..
그렇게 턴이 끝나면 턴에 1더하고 %2해서 무조건 상대에게 턴을 넘길 수 있도록 설계해뒀다.
아 참고로 턴이 반복되는 조건은 누구 하나 죽어서 health[0] 혹은 health[1] 둘 중 하나라도 0이하가 되었을 경우이다. 만약 health[0]즉 내 체력이 0이하가 되었을 경우 0(획득점수)을 반환한다.
반대로 내가 이겼을 경우에는
위와 같이 점수가 산정된다.
다시 메인으로 돌아와서.. 배틀에서 반환된 점수가 곧 번 돈이다. 내가 져서 0을 반환당한 경우가 아니면, 이겼다는 알림과 함께 번 돈을 알려주고, 그만큼 머니에 더해준다.
번 게 0일 경우 적이 이겼다고 알려주고, 이렇게 shop -> battle을 3번 반복한다.
3회 반복 끝나면 보스랑 싸울 시간임.. 보스랑 doBattle해서 이기면(0을 반환당한 게 아니면) 플래그를 얻을 수 있다.
참고로 보스 스펙 이거임 ㅅㅂ ㅋㅋ 내가 무조건 공격할 수 있다고 쳐도 블락 확률이 1/250 ㅅㅂ ㅋㅋ 근데 health가 1이라 공격 한번이라도 성공하면 되는데, 이게 내가 턴을 가져오려면 상점에서 우선순위 강화 5개를 사서 -1로 만들어야 함. 일단 내가 우선공격권 가져오면 한대만 쳐도 무조건 이길 수는 있음. 근데 사실 방어 확률이 1/250이면 브포때릴만하지 않나? 생각했는데 이게 잔과정이 많아서 브포하기엔 오래걸릴 것 같고, 분명 필승법이 있을 것 같아서 브포는 아닌듯.
근데 문제는 우선순위 강화가 좀 비싸다. 20달러임. 아무래도 아까 %s취약점으로 샵에서 뭔 짓을 해야할 것 같다. 우선순위를 못 가져오면 249/250의 확률로 500 ~ 1000의 공격을 받고 사망하게 된다.
umm 20자 입력할 공간에 30자 입력하니까 갑자기 토탈 프라이스 -20이라면서 돈을 줬다... 토탈프라이스는 qint와 price의 곱으로 만들어짐. 둘 중 하나에 문제가 있었단건데, 퀀티티에 너무 큰 값을 입력해서 그게 -부호 없이도 음수로 인식된건가? 그럼 딱 20자만 넣어보자.
음 역시 프라이스 문제는 아니었다.이렇게 되면 개꿀임.
왠지 각이 보여서 19개 입력하니 돈 왕창 줌.
이정도면 걍 HP랑 ATTACK을 오지게 사도 될듯.
ㅋㅋ무조건 내가 먼저임. 참고로 실제로 할 때에는 HP랑 ATK도 오지게 늘렸음.
그리고 PRI가 저꼴이니 무조건 내가 우선순위 가져오고, ATK값이 커서 블락될 확률도 없지만서도 혹시모르니 범위 밖 숫자 입력해서 블락안되게 함. 내 ATK는 엄청 높으니까 무조건 한방컷 할 수 있음.
그렇게 보스까지 한방컷 총 4마리 해치우면 플래그 준다:)
'Hack > CTF' 카테고리의 다른 글
[POXX 2022 본선] Write-up? (0) | 2023.02.28 |
---|---|
[LACTF 2023] stuff (4) | 2023.02.15 |
[MHSCTF 2023] Feb. 1 — Balloons (0) | 2023.02.15 |
[LACTF 2023] rut-roh-relro (0) | 2023.02.14 |
[LACTF 2023] rickroll(Write-up) (0) | 2023.02.14 |