문제 설명


문제 이름처럼 로그인할 수 있는 창이 있다. 

너무 눌러 보라는 듯이 get source 버튼이 있길래 눌러 보니, 소스코드가 나온다. 

 

<?php

if (isset($_GET['view-source'])) {
    show_source(__FILE__);
    exit();
}

/*
create table user(
 idx int auto_increment primary key,
 id char(32),
 ps char(32)
);
*/

 if(isset($_POST['id']) && isset($_POST['ps'])){
  include("./lib.php"); # include for $FLAG, $DB_username, $DB_password.

  $conn = mysqli_connect("localhost", $DB_username, $DB_password, "login_filtering");
  mysqli_query($conn, "set names utf8");

  $id = mysqli_real_escape_string($conn, trim($_POST['id']));
  $ps = mysqli_real_escape_string($conn, trim($_POST['ps']));

  $row=mysqli_fetch_array(mysqli_query($conn, "select * from user where id='$id' and ps=md5('$ps')"));
  if(isset($row['id'])){
   if($id=='guest' || $id=='blueh4g'){
    echo "your account is blocked";
   }else{
    echo "login ok"."<br />";
    echo "FLAG : ".$FLAG;
   }
  }else{
   echo "wrong..";
  }
 }
?>
<!DOCTYPE html>
<style>
 * {margin:0; padding:0;}
 body {background-color:#ddd;}
 #mdiv {width:200px; text-align:center; margin:50px auto;}
 input[type=text],input[type=[password] {width:100px;}
 td {text-align:center;}
</style>
<body>
<form method="post" action="./">
<div id="mdiv">
<table>
<tr><td>ID</td><td><input type="text" name="id" /></td></tr>
<tr><td>PW</td><td><input type="password" name="ps" /></td></tr>
<tr><td colspan="2"><input type="submit" value="login" /></td></tr>
</table>
 <div><a href='?view-source'>get source</a></div>
</form>
</div>
</body>
<!--

you have blocked accounts.

guest / guest
blueh4g / blueh4g1234ps

-->

코드 마지막쪽에 guest와 blueh4g라는 아이디/비번 쌍으로 추정되는p것이 있어서 먼저 로그인 시도를 해 본다.

 

guest / guest 로그인 결과
blueh4g / blueh4g1234ps 로그인 결과

'you have blocked accounts' 라고 나와있듯이... 정말 blocked 된 계정이라고 나온다. 

아예 엉뚱한 아이디와 비번으로 로그인에 시도하면 wrong.. 라고 나오는 걸로 봐서, 위 두 가지 계정은 존재하나, 막혀있는 것임을 확신할 수 있다. 

이 막혀있는 계정을 이용해 로그인에 성공한 뒤 플래그를 획득하는 형식의 문제이다. 

 

다시 소스코드로 돌아가 살펴 본다. 

소스코드에서 php, Mysql 등 익숙한 키워드를 볼 수 있다. 

예전에 풀었던 어떤 문제에서 봤던 것도 같은데... 기억이 가물가물하기 때문에 이 개념부터 다시 찾아 봤다. 

php(Personal Home Page Tools): 웹사이트 제작에 특화된 백엔드 언어. 동적인 웹 페이지를 만들기 위해 설계됨
MySQL: 오픈 소스의 관계형 데이터베이스 관리 시스템.

 

코드 상에서는

   if($id=='guest' || $id=='blueh4g'){
    echo "your account is blocked";

이러한 형태로, id인 'guest'와 'blueh4g'가 입력될 경우 무조건 blocked를 출력하게끔 제한해 두고 있다.

하지만 위에 언급한 것처럼 MySQL로 짜여진 코드이고

MySQL은 대소문자 구분을 하지 않는다.

 

그렇기 때문에, id를 교묘하게 대문자로 바꾸어 동일한 pw로 로그인하면 로그인이 가능하단 소리이다. 

GUEST / guest 로 로그인을 시도해 본다. 

 

플래그 획득에 성공했다. 

'SWUFORCE > 워게임 풀이' 카테고리의 다른 글

[Dreamhack] littlevsbig (misc)  (0) 2024.08.06
[Dreamhack] image-storage (web)  (1) 2024.07.22
[wargame.kr] fly me to the moon (web)  (0) 2024.07.16
[Dreamhack] simple_sqli_chatgpt (web)  (0) 2024.07.02
[Dreamhack] session (web)  (1) 2024.07.02

문제 설명 


생성된 서버에 들어가면 이렇게 고전 게임같은 화면이 나온다. 

 

클릭해서 게임을 진행해 보면,

이렇게 전투기를 마우스포인터로 조종해 초록색 블록에 닿지 않게 해야 하는 간단한 방식인 것을 알 수 있다.

 

초록색 블록에 닿아 패배하고 나면 위와 같이 스코어 31337점을 획득해야 한다는 메시지가 나온다.

31337점을 획득하면 플래그를 얻을 수 있다는 뜻으로 해석해 볼 수 있다.

게임을 통해 31337점을 획득하여 문제를 풀이하라는 뜻은 아닐 것이므로... 소스 코드를 열어 봤다.

 

문제 설명에서부터 자바스크립트 게임이라고 명시되어 있기 때문에, 자바스크립트 소스코드를 확인해 봤다. 

자바스크립트 코드 전체를 살펴 보니 길이가 제법 길고 난독화 되어있다.

eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--){d[c]=k[c]||c}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('76 58=["\\89\\66\\68\\68\\154\\68\\67\\92\\59\\71","\\70\\74\\59\\70\\89\\136\\66\\86\\59","\\81\\59\\63\\118\\70\\61\\71\\59","\\124\\66\\64\\70\\118\\70\\61\\71\\59","\\69\\74\\71\\66\\64\\89\\98\\78\\64\\64\\59\\68","\\97\\66\\84\\63\\74\\98\\78\\64\\64\\59\\68","\\61\\104\\148\\59\\70\\63","\\159\\61\\90\\70\\74\\59\\67\\63\\66\\64\\81\\155\\90\\66\\86\\90\\92\\61\\78\\90\\70\\67\\64","\\97\\67\\71\\64","\\61\\86\\86\\69\\59\\63\\136\\59\\86\\63","\\63\\78\\64\\64\\59\\68","\\81\\59\\63\\170\\68\\59\\85\\59\\64\\63\\124\\92\\142\\84","\\63\\61\\77","","\\77\\112","\\70\\69\\69","\\84\\66\\69\\77\\68\\67\\92","\\104\\68\\61\\70\\89","\\59\\67\\70\\74","\\66\\85\\81\\107\\68\\59\\86\\63\\111\\97\\67\\68\\68","\\66\\85\\81\\107\\71\\66\\81\\74\\63\\111\\97\\67\\68\\68","\\91\\74\\66\\81\\74\\111\\69\\70\\61\\71\\59\\69","\\71\\59\\85\\61\\103\\59","\\63\\67\\104\\68\\59","\\64\\61\\64\\59","\\84\\66\\103\\91\\69\\70\\61\\71\\59\\111\\63\\67\\104\\68\\59","\\70\\68\\66\\70\\89","\\63\\59\\112\\63","\\69\\77\\67\\64\\91\\69\\70\\61\\71\\59","\\68\\59\\86\\63","\\66\\85\\81\\91\\69\\74\\66\\77","\\69\\68\\61\\97","\\86\\67\\84\\59\\142\\64","\\104\\67\\70\\89\\81\\71\\61\\78\\64\\84\\149\\77\\61\\69\\66\\63\\66\\61\\64","\\168\\167\\164\\90","\\84\\66\\103\\91\\63\\78\\64\\64\\59\\68","\\71\\67\\64\\84\\61\\85","\\86\\68\\61\\61\\71","\\78\\77\\84\\67\\63\\59\\98\\78\\64\\64\\59\\68\\143\\150","\\86\\67\\84\\59\\151\\78\\63","\\154\\151\\118\\98","\\74\\66\\81\\74\\149\\69\\70\\61\\71\\59\\69\\107\\77\\74\\77","\\63\\61\\89\\59\\64\\146","\\169\\69\\70\\61\\71\\59\\146","\\67\\148\\67\\112","\\74\\63\\85\\68","\\77\\91\\97\\59\\68\\70\\61\\85\\59","\\78\\77\\84\\67\\63\\59\\98\\61\\89\\59\\64\\143\\150","\\63\\74\\112\\155\\90\\152\\74\\71\\66\\69\\63\\66\\67\\64\\90\\145\\61\\64\\63\\61\\92\\67","\\85\\61\\78\\69\\59\\61\\103\\59\\71","\\91\\70\\74\\71\\66\\69\\63\\66\\67\\64","\\85\\61\\78\\69\\59\\61\\78\\63","\\71\\59\\67\\84\\92","\\152\\74\\71\\66\\69\\63\\66\\67\\64\\90\\145\\61\\64\\63\\61\\92\\67","\\77\\67\\81\\59\\175","\\85\\61\\78\\69\\59\\85\\61\\103\\59","\\63\\61\\89\\59\\64\\107\\77\\74\\77","\\81\\59\\63"];62 119(){76 174=73;76 108=93;62 141(){108=173;79 93};62 130(){79 108};73[58[0]]=62(){141();79 93};73[58[1]]=62(){79 130()};76 116=0;62 131(){79 116};62 133(){72(108){116++};79 93};73[58[2]]=62(){79 131()};73[58[3]]=62(){133();79 93};76 123=161;62 138(){123-=20;79 93};62 144(){79 123};73[58[4]]=62(){138();79 93};73[58[5]]=62(){79 144()}};76 95=0;76 110=0;76 134=125;76 75=117;76 94=117;76 101=0;76 102=0;76 99=0;76 96=0;82=106 127(20);88=106 127(20);62 153(){87=106 119();72(58[6]==135 105){105[58[8]](58[7])};110=121[58[11]](58[10])[58[9]];134+=110;65=0;122(65=0;65<20;65++){82[65]=80;88[65]=137};$(58[19])[58[18]](62(83){65=83*25;$(73)[58[15]](58[12],58[13]+65+58[14]);$(73)[58[15]](58[16],58[17])});$(58[20])[58[18]](62(83){65=83*25;$(73)[58[15]](58[12],58[13]+65+58[14]);$(73)[58[15]](58[16],58[17])});$(58[25])[58[26]](62(){$(58[23])[58[22]](58[21]);$(58[25])[58[15]](58[16],58[24]);132();114()})};62 132(){87=106 119();72(58[6]==135 105){105[58[8]](58[7])};75=117;101=0;102=0;99=0;$(58[28])[58[27]](58[13]+0);$(58[30])[58[15]](58[29],75+58[14]);65=0;122(65=0;65<20;65++){82[65]=80;88[65]=137};$(58[30])[58[32]](58[31]);$(58[19])[58[18]](62(83){65=83*25;$(73)[58[15]](58[12],58[13]+65+58[14]);$(73)[58[15]](58[16],58[17])});$(58[20])[58[18]](62(83){65=83*25;$(73)[58[15]](58[12],58[13]+65+58[14]);$(73)[58[15]](58[16],58[17])})};62 114(){95=95+2;72(95>20){95=0};$(58[35])[58[15]](58[33],58[34]+95+58[14]);72(75+32<125){72(75+46<94){75+=4}109{72(75+16<94){75+=2}}};72(75>0){72(75-14>94){75-=4}109{72(75+16>94){75-=2}}};$(58[30])[58[15]](58[29],75+58[14]);102++;72(102>60){102=0;96=126[58[37]](126[58[36]]()*2)};72(82[0]<10){96=1}109{72(88[0]>166){96=0}};65=0;122(65=20;65>0;65--){82[65]=82[65-1];88[65]=88[65-1]};72(96==0){82[0]-=3};72(96==1){82[0]+=3};88[0]=82[0]+87[58[5]]();$(58[19])[58[18]](62(83){$(73)[58[15]](58[29],58[13]+82[83]+58[14])});$(58[20])[58[18]](62(83){$(73)[58[15]](58[29],58[13]+88[83]+58[14])});72(87[58[5]]()>=120){99++;72(99>100){99=0;87[58[4]]();82[0]+=10}};101++;72(101>20){101=0;87.165();$(58[28])[58[27]](58[13]+87[58[2]]())};72(75<=82[18]+20||75+32>=88[18]){87[58[0]]()};72(87[58[1]]()){158(58[38],10)}109{$(58[30])[58[39]](58[31]);$(58[19])[58[15]](58[16],58[24]);$(58[20])[58[15]](58[16],58[24]);$[58[44]]({171:58[40],156:58[41],162:58[42]+115+58[43]+87[58[2]](),157:62(113){147(113)}})}};62 160(){79};62 147(113){$(58[25])[58[45]](113);$(58[25])[58[15]](58[16],58[17])};$(121)[58[52]](62(){$(58[46])[58[15]](58[16],58[17]);140();163(58[47],172);$(58[46])[58[26]](62(){$(58[46])[58[15]](58[16],58[24]);153();114()});$(58[50])[58[49]](62(){$(73)[58[45]](58[48])});$(58[50])[58[51]](62(){$(73)[58[45]](139)})});76 139=58[53];$(121)[58[55]](62(129){94=129[58[54]]-110});76 115=58[13];62 140(){$[58[57]](58[56],62(128){115=128})};',10,176,'||||||||||||||||||||||||||||||||||||||||||||||||||||||||||_0x32bb|x65||x6F|function|x74|x6E|y|x69|x61|x6C|x73|x63|x72|if|this|x68|ship_x|var|x70|x75|return||x67|left_wall|_0x8618x16|x64|x6D|x66|BTunnelGame|right_wall|x6B|x20|x23|x79|true|pos_x|bg_val|t_state|x77|x54|c_w||c_s|c_r|x76|x62|console|new|x2E|_0x8618x3|else|rail_left|x5F|x78|_0x8618x19|updateTunnel|token|_0x8618x6|234|x53|secureGame||document|for|_0x8618x9|x42|500|Math|Array|_0x8618x20|_0x8618x1d|_0x8618x5|_0x8618x7|restartTunnel|_0x8618x8|rail_right|typeof|x4C|400|_0x8618xa|temp|updateToken|_0x8618x4|x49|x28|_0x8618xb|x4D|x3D|showHighScores|x6A|x2D|x29|x4F|x43|initTunnel|x50|x2C|url|success|setTimeout|x44|scoreUpdate|320|data|setInterval|x25|BincScore|470|x30|x35|x26|x45|type|10000|false|_0x8618x2|x58'.split('|'),0,{}))

 

난독화된 것을 해석하기 위해 아래 사이트를 이용했다. 

https://beautifier.io/

 

Online JavaScript beautifier

Beautify JavaScript, JSON, React.js, HTML, CSS, SCSS, and SASS

beautifier.io

 

function secureGame() {
	var _0x8618x2 = this;
	var _0x8618x3 = true;
	function _0x8618x4() {
		_0x8618x3 = false;
		return true
	};
	function _0x8618x5() {
		return _0x8618x3
	};
	this[_0x32bb[0]] = function () {
		_0x8618x4();
		return true
	};
	this[_0x32bb[1]] = function () {
		return _0x8618x5()
	};
	var _0x8618x6 = 0;
	function _0x8618x7() {
		return _0x8618x6
	};
	function _0x8618x8() {
		if (_0x8618x3) {
			_0x8618x6++
		};
		return true
	};
	this[_0x32bb[2]] = function () {
		return _0x8618x7()
	};
	this[_0x32bb[3]] = function () {
		_0x8618x8();
		return true
	};
	var _0x8618x9 = 320;
	function _0x8618xa() {
		_0x8618x9 -= 20;
		return true
	};
	function _0x8618xb() {
		return _0x8618x9
	};
	this[_0x32bb[4]] = function () {
		_0x8618xa();
		return true
	};
	this[_0x32bb[5]] = function () {
		return _0x8618xb()
	}
};
var bg_val = 0;
var rail_left = 0;
var rail_right = 500;
var ship_x = 234;
var pos_x = 234;
var c_s = 0;
var c_r = 0;
var c_w = 0;
var t_state = 0;
left_wall = new Array(20);
right_wall = new Array(20);
function initTunnel() {
	BTunnelGame = new secureGame();
	if (_0x32bb[6] == typeof console) {
		console[_0x32bb[8]](_0x32bb[7])
	};
	rail_left = document[_0x32bb[11]](_0x32bb[10])[_0x32bb[9]];
	rail_right += rail_left;
	y = 0;
	for (y = 0; y < 20; y++) {
		left_wall[y] = 80;
		right_wall[y] = 400
	};
	$(_0x32bb[19])[_0x32bb[18]](function (_0x8618x16) {
		y = _0x8618x16 * 25;
		$(this)[_0x32bb[15]](_0x32bb[12], _0x32bb[13] + y + _0x32bb[14]);
		$(this)[_0x32bb[15]](_0x32bb[16], _0x32bb[17])
	});
	$(_0x32bb[20])[_0x32bb[18]](function (_0x8618x16) {
		y = _0x8618x16 * 25;
		$(this)[_0x32bb[15]](_0x32bb[12], _0x32bb[13] + y + _0x32bb[14]);
		$(this)[_0x32bb[15]](_0x32bb[16], _0x32bb[17])
	});
	$(_0x32bb[25])[_0x32bb[26]](function () {
		$(_0x32bb[23])[_0x32bb[22]](_0x32bb[21]);
		$(_0x32bb[25])[_0x32bb[15]](_0x32bb[16], _0x32bb[24]);
		restartTunnel();
		updateTunnel()
	})
};
function restartTunnel() {
	BTunnelGame = new secureGame();
	if (_0x32bb[6] == typeof console) {
		console[_0x32bb[8]](_0x32bb[7])
	};
	ship_x = 234;
	c_s = 0;
	c_r = 0;
	c_w = 0;
	$(_0x32bb[28])[_0x32bb[27]](_0x32bb[13] + 0);
	$(_0x32bb[30])[_0x32bb[15]](_0x32bb[29], ship_x + _0x32bb[14]);
	y = 0;
	for (y = 0; y < 20; y++) {
		left_wall[y] = 80;
		right_wall[y] = 400
	};
	$(_0x32bb[30])[_0x32bb[32]](_0x32bb[31]);
	$(_0x32bb[19])[_0x32bb[18]](function (_0x8618x16) {
		y = _0x8618x16 * 25;
		$(this)[_0x32bb[15]](_0x32bb[12], _0x32bb[13] + y + _0x32bb[14]);
		$(this)[_0x32bb[15]](_0x32bb[16], _0x32bb[17])
	});
	$(_0x32bb[20])[_0x32bb[18]](function (_0x8618x16) {
		y = _0x8618x16 * 25;
		$(this)[_0x32bb[15]](_0x32bb[12], _0x32bb[13] + y + _0x32bb[14]);
		$(this)[_0x32bb[15]](_0x32bb[16], _0x32bb[17])
	})
};
function updateTunnel() {
	bg_val = bg_val + 2;
	if (bg_val > 20) {
		bg_val = 0
	};
	$(_0x32bb[35])[_0x32bb[15]](_0x32bb[33], _0x32bb[34] + bg_val + _0x32bb[14]);
	if (ship_x + 32 < 500) {
		if (ship_x + 46 < pos_x) {
			ship_x += 4
		} else {
			if (ship_x + 16 < pos_x) {
				ship_x += 2
			}
		}
	};
	if (ship_x > 0) {
		if (ship_x - 14 > pos_x) {
			ship_x -= 4
		} else {
			if (ship_x + 16 > pos_x) {
				ship_x -= 2
			}
		}
	};
	$(_0x32bb[30])[_0x32bb[15]](_0x32bb[29], ship_x + _0x32bb[14]);
	c_r++;
	if (c_r > 60) {
		c_r = 0;
		t_state = Math[_0x32bb[37]](Math[_0x32bb[36]]() * 2)
	};
	if (left_wall[0] < 10) {
		t_state = 1
	} else {
		if (right_wall[0] > 470) {
			t_state = 0
		}
	};
	y = 0;
	for (y = 20; y > 0; y--) {
		left_wall[y] = left_wall[y - 1];
		right_wall[y] = right_wall[y - 1]
	};
	if (t_state == 0) {
		left_wall[0] -= 3
	};
	if (t_state == 1) {
		left_wall[0] += 3
	};
	right_wall[0] = left_wall[0] + BTunnelGame[_0x32bb[5]]();
	$(_0x32bb[19])[_0x32bb[18]](function (_0x8618x16) {
		$(this)[_0x32bb[15]](_0x32bb[29], _0x32bb[13] + left_wall[_0x8618x16] + _0x32bb[14])
	});
	$(_0x32bb[20])[_0x32bb[18]](function (_0x8618x16) {
		$(this)[_0x32bb[15]](_0x32bb[29], _0x32bb[13] + right_wall[_0x8618x16] + _0x32bb[14])
	});
	if (BTunnelGame[_0x32bb[5]]() >= 120) {
		c_w++;
		if (c_w > 100) {
			c_w = 0;
			BTunnelGame[_0x32bb[4]]();
			left_wall[0] += 10
		}
	};
	c_s++;
	if (c_s > 20) {
		c_s = 0;
		BTunnelGame.BincScore();
		$(_0x32bb[28])[_0x32bb[27]](_0x32bb[13] + BTunnelGame[_0x32bb[2]]())
	};
	if (ship_x <= left_wall[18] + 20 || ship_x + 32 >= right_wall[18]) {
		BTunnelGame[_0x32bb[0]]()
	};
	if (BTunnelGame[_0x32bb[1]]()) {
		setTimeout(_0x32bb[38], 10)
	} else {
		$(_0x32bb[30])[_0x32bb[39]](_0x32bb[31]);
		$(_0x32bb[19])[_0x32bb[15]](_0x32bb[16], _0x32bb[24]);
		$(_0x32bb[20])[_0x32bb[15]](_0x32bb[16], _0x32bb[24]);
		$[_0x32bb[44]]({
			type: _0x32bb[40],
			url: _0x32bb[41],
			data: _0x32bb[42] + token + _0x32bb[43] + BTunnelGame[_0x32bb[2]](),
			success: function (_0x8618x19) {
				showHighScores(_0x8618x19)
			}
		})
	}
};
function scoreUpdate() {
	return
};
function showHighScores(_0x8618x19) {
	$(_0x32bb[25])[_0x32bb[45]](_0x8618x19);
	$(_0x32bb[25])[_0x32bb[15]](_0x32bb[16], _0x32bb[17])
};
$(document)[_0x32bb[52]](function () {
	$(_0x32bb[46])[_0x32bb[15]](_0x32bb[16], _0x32bb[17]);
	updateToken();
	setInterval(_0x32bb[47], 10000);
	$(_0x32bb[46])[_0x32bb[26]](function () {
		$(_0x32bb[46])[_0x32bb[15]](_0x32bb[16], _0x32bb[24]);
		initTunnel();
		updateTunnel()
	});
	$(_0x32bb[50])[_0x32bb[49]](function () {
		$(this)[_0x32bb[45]](_0x32bb[48])
	});
	$(_0x32bb[50])[_0x32bb[51]](function () {
		$(this)[_0x32bb[45]](temp)
	})
});
var temp = _0x32bb[53];
$(document)[_0x32bb[55]](function (_0x8618x1d) {
	pos_x = _0x8618x1d[_0x32bb[54]] - rail_left
});
var token = _0x32bb[13];
function updateToken() {
	$[_0x32bb[57]](_0x32bb[56], function (_0x8618x20) {
		token = _0x8618x20
	})
};

코드를 해석하면 이렇게 비교적 보기 좋은 형태가 된다. 

그러나 길이가 너무 길어서, 찬찬히 훑어 보며 점수와 관련된 부분을 찾아 봤다. (31337점 이상이어야 플래그가 나올 것이므로)

 

	if (BTunnelGame[_0x32bb[1]]()) {
		setTimeout(_0x32bb[38], 10)
	} else {
		$(_0x32bb[30])[_0x32bb[39]](_0x32bb[31]);
		$(_0x32bb[19])[_0x32bb[15]](_0x32bb[16], _0x32bb[24]);
		$(_0x32bb[20])[_0x32bb[15]](_0x32bb[16], _0x32bb[24]);
		$[_0x32bb[44]]({
			type: _0x32bb[40],
			url: _0x32bb[41],
			data: _0x32bb[42] + token + _0x32bb[43] + BTunnelGame[_0x32bb[2]](),
			success: function (_0x8618x19) {
				showHighScores(_0x8618x19)
			}
		})
	}

'showHighScores'라는 것으로 미루어 봤을 때 여기인 것 같다. 

BTunnelGame의 매개변수로 있는 [_0x32bb[2]]의 return값을 31337보다 큰 값으로 수정해 console에 입력해 보겠다.

 

이렇게 한 뒤, 다시 게임을 실행하고 죽었더니

 

위와 같이 score 값도 내가 임의로 입력한 수 '99999'로 설정되고, Flag 획득에 성공했다.

'SWUFORCE > 워게임 풀이' 카테고리의 다른 글

[Dreamhack] image-storage (web)  (1) 2024.07.22
[wargame.kr] login filtering (web)  (0) 2024.07.16
[Dreamhack] simple_sqli_chatgpt (web)  (0) 2024.07.02
[Dreamhack] session (web)  (1) 2024.07.02
[Dreamhack] Path Finder (misc)  (0) 2024.05.28

TCP/IP

1. IP 헤더에 포함이 되지 않는 필드는?

①  ACK → TCP 헤더에 있는 필드임.

② Version    

③ Header checksum

④ Header length

 

3. ′255.255.255.224′인 서브넷에 최대 할당 가능한 호스트 수 는?    

① 2개

② 6개    

③ 14개

④ 30개 → 해당 서브넷을 2진수로 변환하면 11111111.11111111.11111111.11100000이다.

호스트 ID로 할당 가능한 비트는 마지막 '00000'이므로, 이를 10진수 계산으로 변경하면 (16+8+4+2+1=)32이다.

여기에서 게이트웨이인 1과, 브로드캐스트인 256을 제외하면 32-2=30이 된다.

 

6. 서브넷 마스크(Subnet Mask)에 대한 설명으로 옳지 않은 것은?   

①  A, B, C Class 대역의 IP Address는 모두 같은 서브넷 마스크를 사용한다.

→ Class A: 255.0.0.0

Class B: 255.255.0.0

Class C: 255.255.255.0

이므로, 세 대역의 IP Address는 모두 다른 서브넷 마스크를 사용한다.

② 하나의 네트워크 클래스를 여러 개의 네트워크로 분리하여 IP Address를 효율적으로 사용할 수 있다.    

③ 서브넷 마스크는 목적지 호스트의 IP Address가 동일 네트워크상에 있는지 확인한다.    

④ 서브넷 마스크를 이용하면, Traffic 관리 및 제어가 가능하다

 

 


개념 정리

  • STMP
    • 'Simple Mail Transfer Protocol'의 약자
    • 인터넷 전자 우편을 위한 프로토콜
  • TFTP
    • 'Trivial File Transfer Protocol'의 약자
    • UDP 이용. (속도가 빠른 대신 데이터 성공적 전달 보장 불가)
  • ARP
    • IP Adress 이용해 물리적인 네트워크 주소(MAC) 얻음
  • OSI 7계층의 계층별 PDU 명칭(Protocol Data Unit)
    1. 물리 계층: 비트
    2. 데이터링크 계층: 프레임
    3. 네트워크 계층: 패킷
    4. 전송 계층: 데이터그램
    5. 세션 계층: 메세지
    6. 표현 계층: 메세지
    7. 응용 계층(Application): 메세지

 


네트워크 일반

 


NOS

 


네트워크 운용기기

▼ 아래의 강의를 활용해 학습 및 정리하였습니다. ▼

https://inf.run/zmPL

 

[지금 무료] 기초부터 따라하는 디지털포렌식 강의 | 훈지손 - 인프런

훈지손 | 기초부터 따라하는 디지털포렌식 강의입니다. 강의를 따라하다보면 '물 흐르듯, 자연스럽게' 실력이 늘어가는 강의를 추구합니다., 초보자 눈높이에 딱 맞춘, 원리를 이해하는 디지털

www.inflearn.com


ThumbnailCache

  • 내 컴퓨터에 이런 기록들이 남나?
  • 썸네일(Thumbnail): 미리보기 파일
  • Windows에서는 썸네일 사진들을 미리 생성하여 보관하고 있음. 
    • db에 썸네일을 크기별로 저장해 갖고 있게 됨. 
  • 다양한 형태의 썸네일을 지원.
  • 포렌식적 의미
    • 분석 대상 PC에 해당 파일이 존재하였음을 나타냄
    • 해당 파일이 삭제되더라도 ThumbnailCache는 사라지지 않음
  • "Thumbcache Viewer"

 

IconCache

  • Winodws 아이콘(Icon)을 보여주기 위해서 가지고 있는 캐시
    • 공통의 아이콘을 사용(일반적인 폴더, 파일)
    • 별도의 아이콘을 사용(응용 프로그램)
  • Windows에서는 아이콘 사진들을 별도의 공간에 모아서 보관함.
  • 포렌식적 의미
    • 분석 대상 PC에 존재했던 응용 프로그램의 종류를 확인 가능
    • 외부저장매체 사용 흔적 파악
    • 안티포렌식 도구 사용 흔적, 악성코드 실행 흔적 파악
    • 해당 응용프로그램이 삭제되더라도 IconCache는 사라지지 않음

 

Windows Timeline

  • 새로 나온 기술. 데이터 아주 세세하게 남음. 
  • Windows에서 지원하는 Timeline 기능
    • 사용자가 실행하고 있는 응용프로그램
    • 사용자가 과거에 실행했던 응용프로그램
    • 최대 30일의 사용자 행위를 보관
  • Windows + Tab 버튼
  • 설정 활성화
    • '이 장치에 내 활동 기록 저장' 설정
  • Timeline 데이터 저장 경로
    • 유저 계정에 따라 경로가 달라짐
      • 로컬 계정: L.{로컬 계정명}
      • 마이크로소프트 계정: {마이크로소프트 식별자(CID)}
      • Office 365&AAD 계정: AAD.{보안 식별자(SID)}
  • ActivitesChace.db 구조
    • 여러 테이블이 있지만, 아래 세 테이블만 주의깊게 보면 됨. 
    • Activity: 응용프로그램 실행 기록, 실행 시간 등 보통의 Timeline 데이터
    • ActivityOperation: 생성 혹은 삭제 이벤트에 대한 Timeline 데이터
    • Activity_PackageId: 앱별 패키지 이름
  • Windows 10에서 2018년부터 추가된 기능
    • Windows 11부터는 지원 중단
    • 그러나, 동일한 경로에 데이터가 그대로 생성됨.
    • 동작 아티팩트 구조가 조금 다를 수는 있어도, 유사한 데이터가 남는다. 
  • 포렌식적 의미
    • 시간에 따른 사용자의 행위 추적
    • 응용프로그램의 구체적은 사용 시각을 알 수 있음.
  • 'DB Bowser for SQLite'

 


Q. Windows 10에서 2018년부터 추가된 기능 중에 활동 기록 메뉴는 사라졌다. (o/x)

A. X

 

Q. Windows Timeline은 최대 __일의 사용자 행위를 보관한다 (빈칸 채우기)

A. 30일

'SWUFORCE > 디지털 포렌식' 카테고리의 다른 글

디지털 포렌식_08  (0) 2024.07.19
디지털 포렌식_06  (0) 2024.07.03
디지털 포렌식_05  (0) 2024.05.21
디지털 포렌식_04  (0) 2024.05.15
디지털 포렌식_03  (0) 2024.05.07

▼ 아래의 강의를 활용해 학습 및 정리하였습니다. ▼

https://inf.run/zmPL

 

[지금 무료] 기초부터 따라하는 디지털포렌식 강의 | 훈지손 - 인프런

훈지손 | 기초부터 따라하는 디지털포렌식 강의입니다. 강의를 따라하다보면 '물 흐르듯, 자연스럽게' 실력이 늘어가는 강의를 추구합니다., 초보자 눈높이에 딱 맞춘, 원리를 이해하는 디지털

www.inflearn.com


MUICache

  • 윈도우즈에서 다중 언어를 지원하기 위해 존재하는 캐시
  • 실행파일 별로, 유저 언어 이름을 별도로 저장
  • 응용프로그램 실행 시 캐시에 기록 남음
    • 실행 파일 경로, 이름
    • 실행 파일 삭제되거나 경로 변경된 경우에도 기록 지워지지 않음
  • 경로가 레지스트리
    • 레지스트리 속에 있는 개념?

 

AmCache

  • 응용프로그램과 운영체제의 호환성을 위해 존재하는 캐시
    • 운영체제 업데이트되면 DLL이 생성 혹은 삭제 → 호환성 문제 발생
    • Windows에서는 프로그램 호환성 관리자를 이용하여 이 문제를 해결
  • 모든 실행 파일의 이름, 경로, 크기, 해시값 확인
  • AmCacheParser 이용해 분석

 

ShimCache (= AppCompatCache)

  • 응용프로그램과 운영체제의 호환성을 위해 존재하는 캐시
    • 운영체제 업데이트되면 DLL이 생성 혹은 삭제 → 호환성 문제 발생
    • Windows에서는 프로그램 호환성 관리자를 이용하여 이 문제를 해결

Web Browser Artifacts

  • Web Browser
    • 인터넷을 이용하기 위해 실행하는 응용 프로그램
    • 웹 검색, 로그인, 파일 다운로드, 영상 시청 등
  • Web Browser Artifacts
    • 웹 브라우저가 제공하는 많은 데이터, 기능 등을 포렌식적으로 분석
    • History: 방문한 URL, 방문 횟수, 방문 시각 등
    • Cache: 캐시로 저장되는 이미지, 텍스트, 스크립트, 아이콘, 시간, 크기 등
    • Cookie: 사용자 데이터, 자동 로그인 등
    • Download list: 저장 경로, URL, 크기, 시간, 성공 여부 

Q. 마지막 실행 시간을 확인할 수 있는 캐시는?

A. ShimCache

 

Q. 웹 브라우저를 다른 말로 인터넷이라고 한다. (O/X)

A. X

'SWUFORCE > 디지털 포렌식' 카테고리의 다른 글

디지털 포렌식_08  (0) 2024.07.19
디지털 포렌식_07  (0) 2024.07.10
디지털 포렌식_05  (0) 2024.05.21
디지털 포렌식_04  (0) 2024.05.15
디지털 포렌식_03  (0) 2024.05.07

문제 설명


웹 사이트 들어가 보니,

이렇게 기본적인 형태를 갖추고 있다. 

Home, About, Contact 셋 다 눌러 봐도 이 화면이다. 

 

로그인을 눌러 보면 username이나 pw 입력하라는 건 안 나오고,

userlevel을 입력하라고 한다...

 

문제에선 챗지피티 이용하라고는 했는데 아무런 지식 없이는 어떤 형식으로 질문을 해야 할지 모르겠어서,

일단 소스코드를 먼저 열어 봤다.

#!/usr/bin/python3
from flask import Flask, request, render_template, g
import sqlite3
import os
import binascii

app = Flask(__name__)
app.secret_key = os.urandom(32)

try:
    FLAG = open('./flag.txt', 'r').read()
except:
    FLAG = '[**FLAG**]'

DATABASE = "database.db"
if os.path.exists(DATABASE) == False:
    db = sqlite3.connect(DATABASE)
    db.execute('create table users(userid char(100), userpassword char(100), userlevel integer);')
    db.execute(f'insert into users(userid, userpassword, userlevel) values ("guest", "guest", 0), ("admin", "{binascii.hexlify(os.urandom(16)).decode("utf8")}", 0);')
    db.commit()
    db.close()

def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect(DATABASE)
    db.row_factory = sqlite3.Row
    return db

def query_db(query, one=True):
    cur = get_db().execute(query)
    rv = cur.fetchall()
    cur.close()
    return (rv[0] if rv else None) if one else rv

@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        userlevel = request.form.get('userlevel')
        res = query_db(f"select * from users where userlevel='{userlevel}'")
        if res:
            userid = res[0]
            userlevel = res[2]
            print(userid, userlevel)
            if userid == 'admin' and userlevel == 0:
                return f'hello {userid} flag is {FLAG}'
            return f'<script>alert("hello {userid}");history.go(-1);</script>'
        return '<script>alert("wrong");history.go(-1);</script>'

app.run(host='0.0.0.0', port=8000)

대략 훑어 보니,

    db.execute(f'insert into users(userid, userpassword, userlevel) values ("guest", "guest", 0), ("admin", "{binascii.hexlify(os.urandom(16)).decode("utf8")}", 0);')

이런 부분을 대충 짐작해 보자면

userid=guest, userpassword=guest, userlevel=0 인 계정 하나,

userin=admin, userpassword={binascii.hexlify(os.urandom(16)).decode("utf8")}, userlevel=0인 계정 하나

이렇게 두 개의 계정이 있는 듯하다.

아마 플래그를 얻기 위해서 key가 되는 건 admin이겠지

 

어쨌든 위 내용을 바탕으로 login 창에서 userlevel 0 입력해 봤더니,

게스트 계정으로만 로그인이 된다. 

 

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        userlevel = request.form.get('userlevel')
        res = query_db(f"select * from users where userlevel='{userlevel}'")
        if res:
            userid = res[0]
            userlevel = res[2]
            print(userid, userlevel)
            if userid == 'admin' and userlevel == 0:
                return f'hello {userid} flag is {FLAG}'
            return f'<script>alert("hello {userid}");history.go(-1);</script>'
        return '<script>alert("wrong");history.go(-1);</script>'

app.run(host='0.0.0.0', port=8000)

여기서 보면 users 테이블에서 userlevel과 일치하는 행의 모든 컬럼을 반환한다고 한다.

그리고 userid가 admin 문자열과 일치할 경우 flag 값을 출력한다.

 

and 연산자를 사용해 userid 컬럼 값이 admin인 쿼리를 입력하면 문제가 해결된다고 한다. 

플래그 얻기 성공!

문제 설명


 

세션 웹 서버에 들어가면 이와 같은 화면이 나온다. 

'Home' 페이지와 'About' 페이지를 눌렀을 땐 둘 모두 동일하게 위의 화면을 보인다. 

문제 자체에서 '로그인 서비스' 라는 점을 언급하고 있으니, 당연히 'Login' 페이지 중요할 것 같다.

 

 

역시나 'Login'에 들어가면 이렇게 username과 password를 입력할 수 있는 칸이 존재한다. 

 

여기서부터는 문제 파일 속 코드를 참조해 풀이해야 한다.

#!/usr/bin/python3
from flask import Flask, request, render_template, make_response, redirect, url_for

app = Flask(__name__)

try:
    FLAG = open('./flag.txt', 'r').read()
except:
    FLAG = '[**FLAG**]'

users = {
    'guest': 'guest',
    'user': 'user1234',
    'admin': FLAG
}

session_storage = {
}

@app.route('/')
def index():
    session_id = request.cookies.get('sessionid', None)
    try:
        username = session_storage[session_id]
    except KeyError:
        return render_template('index.html')

    return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not admin"}')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    elif request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        try:
            pw = users[username]
        except:
            return '<script>alert("not found user");history.go(-1);</script>'
        if pw == password:
            resp = make_response(redirect(url_for('index')) )
            session_id = os.urandom(4).hex()
            session_storage[session_id] = username
            resp.set_cookie('sessionid', session_id)
            return resp 
        return '<script>alert("wrong password");history.go(-1);</script>'

if __name__ == '__main__':
    import os
    session_storage[os.urandom(1).hex()] = 'admin'
    print(session_storage)
    app.run(host='0.0.0.0', port=8000)

문제 파일에는 이런 형태의 파이썬 코드가 있다. 당연히 문제 서버를 구성하고 있는 코드인 것으로 보인다. 

 

코드의 아래 부분을 참고했을 때, 

users = {
    'guest': 'guest',
    'user': 'user1234',
    'admin': FLAG
}

guest, user, admin 이렇게 세 가지의 username이 존재하며

admin이라는 user에 FLAG에 관한 힌트가 있다는 걸 알 수 있다.

 

guest와 user를 이용해 먼저 로그인을 진행해 보았다. 

guest
user

둘 다 admin이 아니기 때문에... 당연히 플래그를 얻을 순 없었다. 

 

admin에 대한 힌트를 얻기 위해 다시 코드를 훑어 보면,

        if pw == password:
            resp = make_response(redirect(url_for('index')) )
            session_id = os.urandom(4).hex()
            session_storage[session_id] = username
            resp.set_cookie('sessionid', session_id)
            return resp 
        return '<script>alert("wrong password");history.go(-1);</script>'

if __name__ == '__main__':
    import os
    session_storage[os.urandom(1).hex()] = 'admin'
    print(session_storage)
    app.run(host='0.0.0.0', port=8000)

Login 페이지에서 알맞은 password를 입력받으면,

해당 값을 username에 대입되는 pw의 파라미터 값과 대조하여 일치할 시 index 코드로 이동해 플래그를 표시하는 방식이다. 

 

가장 하단 부분 코드에 집중하여 본다면, 

해당 코드가 실행될 때 session_storage[os.urandom(1).hex()] 라는 코드를 통해서 랜덤한 hex값을 생성한 뒤, 그를 admin의 sessionid로 정의한다. 

여기서의 sessionid는 1Byte의 hex값으로 정의된다. (사실 뭔 말인지 잘 모르겠음)

어쨌든, 우리는 0부터 255까지(256가지) 무작위 대입을 통해 값을 구할 순 있다는 것이다.

 

지난번에 다운받았던 Burp suite로 무작위 공격이 가능하다. 

00부터 FF까지 총 256가지 경우의 수 탐색을 하기 위해서는 Burp suite의 intruder 기능을 이용하면 된다.

해당 페이지에서 세션 아이디로 나와 있는 값을 선택해 send to intruder을 한 뒤, intruder 탭에 들어가면

 

이렇게 sessionid 부분이 $로 감싸져 있다. 이 상태에서 payloads에 들어가

 

이와 같이 공격 설정을 한 뒤에 우측 상단 Steart attack을 누르면 

무작위 대입 공격을 자체적으로 진행한다. 

근데 시간이 너무 오래 걸린다...

 

어쨌든 이론 상으로는 이렇게 공격을 진행하다 보면, 혼자만 길이가 다른 값이 나올테니

그 값을 Burp suite나 개발자 도구에서 admin의 세션값으로 넣어 주면 플래그를 얻을 수 있다고 한다. 

다음에 다시 풀어봐야지...

문제 설명


문제 파일 압축을 풀어 보니 chall.c라는 c 코드가 등장한다.

// Name: chall.c
// Compile Option: gcc chall.c -o chall -fno-stack-protector

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define FLAG_SIZE 0x45

void init() {
	setvbuf(stdin, 0, 2, 0);
	setvbuf(stdout, 0, 2, 0);
}

int main(void) {
    int fd;
    char *flag;

    init();

    // read flag
    flag = (char *)malloc(FLAG_SIZE);
    fd = open("./flag", O_RDONLY);
    read(fd, flag, FLAG_SIZE);

    char cmp_str[10] = "Dreamhack";
    char inp_str[10];   
    printf("Enter \"Dreamhack\" : ");
    scanf("%9s", inp_str);

    if(strcmp(cmp_str, inp_str) == 0){
        puts("Welcome Beginners!");
        // print flag
        puts(flag);
    }
    
    return 0;
}

 

그리고 해당 문제는 웹해킹이 아닌 시스템 해킹 문제이므로, 웹해킹 서버로는 아예 접근이 되지 않는다. 

우분투 리눅스 환경에서 nc로 시스템해킹 링크에 접근해 보려 한다.

 

사실 시스템 해킹 문제가 처음이라 조금 헤멜 것 같다고 생각했는데

입력과 동시에 끝나버렸다.

정말 몸풀기용 기초 문제였나보다...

 

'SWUFORCE > 워게임 풀이' 카테고리의 다른 글

[Dreamhack] session (web)  (1) 2024.07.02
[Dreamhack] Path Finder (misc)  (0) 2024.05.28
[Dreamhack] pathtraversal (web)  (0) 2024.05.22
[Dreamhack] web-misconf-1 (web)  (0) 2024.05.14
[Dreamhack] devtools-sources (web)  (0) 2024.05.14

https://www.ahnlab.com/ko/contents/content-center/35594

 

AhnLab | 콘텐츠 센터

 

www.ahnlab.com


타켓형 스캠

  • 사회공학적 기법을 이용해 치밀하게 설계된 공격 시나리오로 진행됨
  • 사전에 수집한 공격 대상 정보를 바탕으로 맞춤형 피싱 시나리오를 구성함
  • 대표적인 타겟형 스캠
    • 비즈니스 이메일 사기(Business Email Compromise, BEC)
    • 스피어 피싱

 

BEC(Business Email Compromise)

  • 이메일을 활용해 주로 기업이나 정부 기관 등의 조직 구성원(특히 고위 임원진, 재무·인사 담당자) 표적
  • 공격 대상에게 업무적으로 연관성 있는 인물로 위장해 기밀 정보 전송을 유도
    • 링크드인(LinkedIn)이나 공개된 웹 사이트를 통해 공격 대상에 대한 사전 정보를 수집
    • 발신 주소 도메인을 스푸핑(Spoofing)하거나 신뢰할 만한 기관을 사칭해 이메일 발송
    • 공격 대상과 신뢰 관계를 쌓은 뒤, 심리적 압박을 가하는 사회공학 기법을 활용해 송금이나 정보 전송을 요구

 

스푸핑(Spoofing):

직접적으로 시스템에 침입을 시도하지 않고 피해자가 공격자의 악의적인 시도에 의한 잘못된 정보 혹은 연결을 신뢰하게끔 만드는 일련의 기법

 

BEC 사례

  1. 홍콩의 한 다국적 기업에서 발생한 사고
    • 공격자들은 AI 딥페이크 기술을 활용해 회사 CFO 사칭하는 이메일을 전송
    • 직원이 의심을 품고 화상 회의를 추가로 진행했지만, CFO 및 임직원들의 모습이 딥페이크로 조작되어 있었음
    • 재무 담당 직원이 이에 속아 2,500달러를 송금
    • AI 기술의 발전으로 인해 딥페이크 등을 이용한 사칭이 더욱 수월해져 BEC 공격의 성공률 또한 높아질 것으로 예상

 

스피어 피싱 

  • 타겟이 악성 파일을 실행하거나, 민감한 데이터를 입력하도록 유도하는 교묘한 방식과 시나리오를 구성

 

스피어 피싱 사례

  1. 내부 직원 사칭
    • 안랩 직원을 대상으로, 이메일 주소 도메인 역시 'ahnlab.com'으로 전송된 메일
    • 음성 메시지 수신을 알리는 내용과 함께 첨부된 파일이 안랩 서비스로 위장한 피싱 페이지로 연결되는 형태
      • 피싱 페이지에는 이메일 수신인의 이름과 이메일 주소가 미리 입력되어 있어 수신인이 로그인을 시도할 시 입력한 계정 정보가 공격자에게 전달됨
  2. 이메일 스레드 연결을 통한 신뢰감 형성
    • 이메일 스레드를 연결해 마치 이전에 여러 차례 소통을 했던 것처럼 사용자를 속임
    • 이메일 제목도 'RE:'로 시작해 이전 대화의 연장선상의 것으로 위장
    • 기업 이메일 작성 관행을 모방해 발신자 서명을 포함하고, 다수의 수신인과 참조인을 지정
    • 본문에는 첨부 파일을 신속히 확인해야 한다고 요구하고 며칠 간격으로 후속 이메일을 전송해 수신인을 재촉
  3. 링크 클릭 유도를 통한 정보 탈취 시도
    • 외부와 빈번히 이메일을 주고받는 직원을 겨냥한 공격
    • 기업의 비즈니스에 관심 있는 척하며 수신인이 특정 링크를 클릭하도록 유도
      • 악성 피싱 페이지로 연결, 첫 번째 사례와 동일한 구조
  4. 타겟의 사회적 관계 악용
    • 공격 대상의 사회적 관계를 사전에 파악해 실제 친분이 있는 인물을 사칭
    • 이메일 발신자 주소의 스펠링을 약간 변경해 실제 주소와 유사하게 위장
    • 사회공학적 기법을 교묘히 활용한 사례
  5. 보안 연구원 대상 스피어 피싱
    • 보안 연구원들의 관심사와 연구 분야를 파악하고 이를 바탕으로 맞춤형 피싱 이메일을 보내 공격을 시도
    • 관심 가질 만한 주제로 블로그를 운영하거나 SNS 통해 친밀도 형성
    • 최신 보안 이슈에 대한 분석 자료라며 악성 코드 포함된 문서 보내거나, 흥미로운 취약점 발견했다며 악성 링크 포함된 이메일 보내는 등의 공격
  6. 채용 제안 사칭
    • 링크드인을 통해 가짜 체용 제안을 보내 보안 리서처들을 공격
    • 채용 담당자로 위장해 접근한 뒤, 왓츠앱(WhatsApp)으로 대화 이어가며 악성코드 포함된 문서 전송하는 수법 사용

+ Recent posts