본문 바로가기

4-1. 2026-1 심화 스터디/워게임 도장깨기

[3주차] 워게임 도장깨기_시스템 해킹

Another Ping 문제풀이

 

1) 먼저 127.0.0.1;ls 로 쉘에서 실행되는지부터 확인한다.

쉘일 가능성은 있지만 ;가 막힌다. 비슷하게 계속 시도하다 보면 공백, |, &, {  등도 막히는 것을 알 수 있다.

 

2) 127.0.0.1`ls`로 백틱('안에 있는 명령부터 실행하는 것) 을 시도한다.

ls 실행되고 출력이 ping에 붙은 것을 알 수 있다. >RCE(서버 조종 가능)가 성공함

templates 한 줄만 보이는 것을 알 수 있다.

 

3) 127.0.0.1`pwd`로 지금 디렉토리 위치를 파악한다.

현재 위치는 /app이다.

 

4) 전체 경로를 많이 출력시켜 주는 find를 써본다.

flag 위치를 확인할 수 있다.

 

5) cat ./flag.txt를 해줘야 하는데 공백을 못쓰니까 $IFS로 바꿔서 cat$IFS./flag.txt로 시도한다.

플래그는 DH{c64c86a3e2121098:xOut/xHnxUuBc8yuFc+4NA==}이다. 

 

 

 

 

 

pwnable.kr [lotto] 문제풀이

 

먼저 문제 설명을 보면

로또 번호를 맞추는 문제 같다.

 

lotto.c를 확인해보니

6바이트를 입력해야 하고

번호는 1~45번까지이다.

이 구조에서는 하나의 lotto[i] 값이 모든 submit[j] 값과 비교되어 같은 값이 여러 개 존재하면 중복으로 카운트되는 문제가 발생한다.

 

예) 만약 로또 숫자 6개 중 1이 있다고 가정한다면, submit = [1, 1, 1, 1, 1, 1]을 했을 때 해당 값이 전부 매칭되어 match가 한번에 6이 증가한다.

따라서 숫자 하나만 맞춰도 match == 6 조건을 만족하게 된다.

입력은 다음과 같이 구성한다.

  • 메뉴 선택: 1
  • 제출값: \x01 6개

이를 반복적으로 전송하면, 로또 숫자 중 하나가 1이 되는 순간 flag를 획득할 수 있다.

bad luck... 문구가 반복적으로 뜨게 된다. 하지만 그 중에서!

 

잘 찾아보면 숨겨진 flag를 찾을 수 있다. 끝!

 

 

pwnable.kr [collision] 문제풀이

 

 

1. cgywin에서 ssh col@pwnable.kr -p2222을 치고 pw인 guest를 쳐서 문제 푸는 환경을 만들어준다.

 

2. ls는 현재 디렉토리 안에 있는 파일 목록을 보여주는 명령어 

 

3. cat col.c를 해서 코드를 본다.

#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC; //맞춰야하는 목표값
unsigned long check_password(const char* p) { // p는 사용자가 입력한 문자열
	int* ip = (int*)p;   // 문자열 -> int 배열로 바꿈
	int i;
	int res=0;
	for(i=0; i<5; i++){ //int 5개 더하고 반환
		res += ip[i];
	}
 	return res;
}
int main(int argc, char* argv[]) {
		if(argc<2){ //문자열을 입력 안 하면 실행 안 됨
				printf("usage : %s [passcode]\n", argv[0]) ;
				return 0;
		}
		if(strlen (argv[1]) != 20){ //입력은 반드시 20바이트
				printf("passcode length should be 20 bytes\n");
				return 0;
		}
		if (hashcode == check_password( argv[1] )) { //입력 값의 합이 목표값과 같으면 성공
				setregid(getegid(), getegid());
				system("/bin/cat flag"); //성공시
				return 0;
         }
         else
         		printf("wrong passcode.\n"); //실패시
   		return 0;
}
col@ubuntu:~$

입력받은 문자열을 메모리에서 보면 (총 20바이트)

[1] [1] [1] [1] [2] [2] [2] [2] [3] [3] [3] [3] [4] [4] [4] [4] [5] [5] [5] [5] 

 

(int*)p를 하고 난 후 메모리에서 보면

문자 하나= 1바이트(ASC||) -> 16진수

'1' = 0x31
'2' = 0x32
'3' = 0x33
'4' = 0x34
'5' = 0x35

[31 31 31 31] [32 32 32 32] [33 33 33 33] [34 34 34 34] [35 35 35 35] 이다

 

int*로 반환되면

[31 31 31 31] → 0x31313131
[32 32 32 32] → 0x32323232
[33 33 33 33] → 0x33333333
[34 34 34 34] → 0x34343434
[35 35 35 35] → 0x35353535 이다

for(i=0; i<5; i++){ //int 5개 더하고 반환
		res += ip[i];
	}

res =
0x31313131 +
0x32323232 +
0x33333333 +
0x34343434 +
0x35353535 이므로 다 더하면

res = 0xFFFFFFFF 이 나온다.

 

 

4. 문제점 분석

문자열을 겁증하는 게 아니라 메모리를 int 배열로 해석해서 더한다.

 

원하는 숫자 5개를 직접 만들어 넣을 수 있다.

-> ip[0] + ip[1] + ip[2] + ip[3] + ip[4] = 0x21DD09EC

 

ip[4] = 0x21DD09EC - 0x04040404
       = 0x1DD905E8

 

./col "$(python2 -c 'import struct; print(struct.pack("<I",0x01010101)*4 + struct.pack("<I",0x1DD905E8))')" 를 입력하면

 

5. 문제 해결 

flag값: Two_hash_collision_Nicely