[Mecab] 영어 명사 추출

예전엔 영어 명사 분리가 잘 안되서 만들었던거 같은데, 지금은 기본 mecab으로도 잘 된다. 결과적으로 필요 없는 글이다.

아마 예전에 mecab을 잘못 설치하거나 이상하게 써서 안됐을지도…

 

dic.txt는 다운받아서 같은 경로에 두면 되며, 데이터는 http://www.114pda.com/language/dic-data/dic-ek-51873.htm에서 가져왔다.

정확도를 높이려면 사전을 추가하면 되는데, https://github.com/liks79/edic/tree/master/data에서 가져오면 될 듯 하다.

var mecab = require('mecab-ffi');
var fs = require('fs');

let tsvParser = (filePath) => {
    let data = fs.readFileSync(filePath, 'utf-8').split('\r\n');
    let result = {};
    for (let i = 0; i < data.length; i++) {
        if (!data[i]) break;
        let item = data[i].split(' /// ');

        if (!item[1] || item[1].length <= 0) {
            item[1] = '';
        }

        result[item[0]] = {eng: item[0], tag: item[1].match(/([A-Z].)/gim), kor: item[1]};
    }

    return result;
};

mecab.siyaParse = (string) => {
    result = mecab.parseSync(string);

    for (let i = 0; i < result.length; i++) {
        if (result[i][1] == 'SL') {
            if (data[result[i][0].toLowerCase()])
                result[i] = [result[i][0], data[result[i][0].toLowerCase()].tag, data[result[i][0].toLowerCase()].kor];
        }
    }

    return result;
}


var data = tsvParser('./dic.txt');

// Synchronously
result = mecab.siyaParse("It is test");
console.log(result);

 

[C/C++] SSD 판별 소스

https://stackoverflow.com/questions/23363115/detecting-ssd-in-windows/33359142

꽤 오래전에 대학 선배가 C언어로 SSD를 판별할 수 있냐고 물어봤다. 찾아보니 MSDN과 stackoverflow에 이미 잘 정리된 코드가 있었다. 사실 검색하면 바로 나오는데, 한글로 정리된 자료는 별로 없는 듯했다. 이에 소스코드를 공유하고자 한다.

 

#include <windows.h>
#include <WinIoCtl.h>
#include <Ntddscsi.h>
#include <tchar.h>
#include <cstddef>
#include <stdio.h>
 
#define ATA_FLAGS_DATA_IN   (1 << 1)
 
#define FILE_DEVICE_CONTROLLER  0x00000004
#define IOCTL_SCSI_BASE         FILE_DEVICE_CONTROLLER
 
#define METHOD_BUFFERED 0
#define FILE_READ_ACCESS    ( 0x0001 )
#define FILE_WRITE_ACCESS   ( 0x0002 )
 
#define kNominalMediaRotRateWordIndex 217
 
struct ATAIdentifyDeviceQuery
{
    ATA_PASS_THROUGH_EX header;
    WORD data[256];
};
 
void deviceInfo(TCHAR param[]) {
    TCHAR defaultPath[8] = _TEXT("\\\\.\\");
    TCHAR letter = param[0];
    TCHAR path[256] = _TEXT("");
    BOOL bIsSSD = FALSE;
    WORD wRPM = 0;
    DWORD bytesReturned;
    HANDLE hDevice = NULL;
     
    _stprintf(path, _TEXT("%s%c:"), defaultPath, letter);
     
    hDevice = CreateFile(path,
        0,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
 
    if (hDevice != INVALID_HANDLE_VALUE){
        _tprintf(_TEXT("TRIM="));
 
        STORAGE_PROPERTY_QUERY spqTrim;
        spqTrim.PropertyId = (STORAGE_PROPERTY_ID)StorageDeviceTrimProperty;
        spqTrim.QueryType = PropertyStandardQuery;
 
        bytesReturned = 0;
        DEVICE_TRIM_DESCRIPTOR dtd = { 0 };
        if (::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
            &spqTrim, sizeof(spqTrim), &dtd, sizeof(dtd), &bytesReturned, NULL) &&
            bytesReturned == sizeof(dtd)){
            _tprintf(_TEXT("%s"), dtd.TrimEnabled ? _TEXT("Y (is SSD)") : _TEXT("N (is HDD)"));
        }
        else{
            int err = ::GetLastError();
            _tprintf(_TEXT("?"));
        }
 
        _tprintf(_TEXT(", seekPenalty="));
 
        STORAGE_PROPERTY_QUERY spqSeekP;
        spqSeekP.PropertyId = (STORAGE_PROPERTY_ID)StorageDeviceSeekPenaltyProperty;
        spqSeekP.QueryType = PropertyStandardQuery;
 
        bytesReturned = 0;
        DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = { 0 };
        if (::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
            &spqSeekP, sizeof(spqSeekP), &dspd, sizeof(dspd), &bytesReturned, NULL) &&
            bytesReturned == sizeof(dspd)){
            _tprintf(_TEXT("%s"), dspd.IncursSeekPenalty ? _TEXT("Y (is HDD)") : _TEXT("N (is SSD)"));
        }
        else{
            int err = ::GetLastError();
            _tprintf(_TEXT("?"));
        }
 
 
        _tprintf(_TEXT(", RPM="));
 
        ATAIdentifyDeviceQuery id_query;
        memset(&id_query, 0, sizeof(id_query));
 
        id_query.header.Length = sizeof(id_query.header);
        id_query.header.AtaFlags = ATA_FLAGS_DATA_IN;
        id_query.header.DataTransferLength = sizeof(id_query.data);
        id_query.header.TimeOutValue = 5;
        id_query.header.DataBufferOffset = offsetof(ATAIdentifyDeviceQuery, data[0]);
        id_query.header.CurrentTaskFile[6] = 0xec; 
 
        bytesReturned = 0;
        if (::DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH,
            &id_query, sizeof(id_query), &id_query, sizeof(id_query), &bytesReturned, NULL) &&
            bytesReturned == sizeof(id_query)){
            _tprintf(_TEXT("%d"), (UINT)id_query.data[kNominalMediaRotRateWordIndex]);
        }
        else{
            int err = ::GetLastError();
            _tprintf(_TEXT("?"));
        }
 
        _tprintf(_TEXT("\n"));
        ::CloseHandle(hDevice);
    }
    else {
        _tprintf(_TEXT("No Directory\n"));
    }
}
 
void main() {
    TCHAR filepath[256];
 
    while (true) {
        ZeroMemory(filepath, sizeof(filepath));
        _tprintf(_TEXT("\n\nInput filepath : "));
        _tscanf(_TEXT("%s"), filepath);
 
        if (isalpha(filepath[0]) && filepath[1] == ':') {
            deviceInfo(filepath);
        }
        else {
            _tprintf(_TEXT("\n\nWrong Path!!\nfilepath example : C:\\YOUR_DIRECTORY\n\n"));
        }
 
        fflush(stdin);
    }
}

 

 

[WordPress] 워드프레스 텍스트 에디터 플러그인

워드프레스에서 제공하는 기본 텍스트 에디터는 쓰기 정말 안좋다. 그 흔한 글자색 변경 기능도 없다. 다행히 플러그인 중 쓸만한 텍스트 에디터 플러그인을 찾았는데, 그 중 하나를 소개할까 한다.

바로  TinyMCE advanced이다.

설치는 늘 그렇듯 워드프레스 어드민 페이지에서 플러그인 > 플러그인 추가하기 > TinyMCE advanced 검색 > 설치 > 활성화를 하면 된다.

그 후 설정 > TinyMCE advanced에서 자신의 취향에 맞게 텍스트 에디터를 손보면 된다.

 

바뀐 에디터

[WordPress] 서버 하나에 워드프레스를 여러개 설치해보자.

서버 Ubuntu 16.04, 호스팅 Hosting.kr를 사용한 환경에서 작성된 글입니다.

 

서버 하나에 워드프레스를 여러개 설치할 일이 생겼다. 우선 새로만드는 사이트에 연결될 도메인을 먼저 설정하자. 도메인 업체는 Hosting.kr밖에 사용해 본 적이 없어서 Hosting.kr을 기준으로 설명하겠다. 먼저 hosting.kr로 들어간다.

 

들어가면 홈에 이런 검색 창이 뜨는데, 원하는 도메인을 검색한다.

 

도메인 현황은 다음과 같이 뜨며, 이미 사용중인 도메인은 등록할 수 없다. 등록 가능한 도메인 중 마음에 드는걸 골랐다면 체크박스에 체크를 해주고 도메인 등록 버튼을 눌러 결제를 진행한다.

 

결제가 끝났다면 상단의 [나의서비스관리]에서 [도메인 관리]를 선택한다.

 

등록한 도메인과 [네임서버설정(무료)] – [네임서버(서브도메인) 설정 관리]에 체크한 다음 신청하기 버튼을 누른다.

 

위와 같은 화면이 떴다면 자신의 서버 IP주소를 등록해주면 된다. 서브도메인을 공란으로 두고 IP주소와 우선순위만 설정하면 도메인이 연결되는거고, 서브도메인까지 작성하면 서브도메인이 연결되는 형태다.

이 글에서는 siya.co.kr 외에 minseo.siya.co.kr에 새 워드프레스를 구축하는 시나리오로 진행된다.

네임서버 설정이 끝났다면 서버에 접속한다. 그 뒤 자신이 마음에 드는 디렉토리에 워드프레스를 설치한다.

 

mkdir -p "YOUR_DIRECTORY"
cd "YOUR_DIRECTORY"
wget https://wordpress.org/latest.tar.gz
tar -zxvf latest.tar.gz
--2017-08-25 23:56:32--  https://wordpress.org/latest.tar.gz
Resolving wordpress.org (wordpress.org)... 66.155.40.249, 66.155.40.250
접속 wordpress.org (wordpress.org)|66.155.40.249|:443... 접속됨.
HTTP request sent, awaiting response... 200 OK
Length: 8178289 (7.8M) [application/octet-stream]
Saving to: ‘latest.tar.gz’

latest.tar.gz          100%[============================>]   7.80M  12.5KB/s    in 7m 5s

2017-08-26 00:03:38 (18.8 KB/s) - ‘latest.tar.gz’ saved [8178289/8178289]


...


wordpress/wp-includes/class-wp-hook.php
wordpress/wp-includes/rest-api.php
wordpress/wp-includes/update.php
wordpress/wp-includes/comment.php
wordpress/wp-includes/class-wp-text-diff-renderer-table.php
wordpress/wp-config-sample.php

이제 ls 명령어를 치면 latest.tar.gz 파일과 wordpress 디렉토리가 있을 것이다. tar파일은 이제 필요가 없으니 삭제하고, wordpress 폴더는 보안상의 이유로 이름을 바꾸는 것이 좋다고 한다. 원하는 이름으로 바꿔주자.

ls
rm latest.tar.gz
mv wordpress/ "YOUR_WORDPRESS_DIR"
cd "YOUR_WORDPRESS_DIR"
ls
latest.tar.gz  wordpress

index.php        wp-admin              wp-content         wp-load.php      wp-signup.php
license.txt      wp-blog-header.php    wp-cron.php        wp-login.php     wp-trackback.php
readme.html      wp-comments-post.php  wp-includes        wp-mail.php      xmlrpc.php
wp-activate.php  wp-config-sample.php  wp-links-opml.php  wp-settings.php

wordpress가 잘 설치되었다. 마지막으로 wp-config-sample.php를 wp-config.php란 이름으로 복사해준다.

cp wp-config-sample.php wp-config.php

 

복사가 끝났으면 vi로 wp-config.php를 열어 DB 정보를 입력해준다. 이것으로 wordpress 설치는 끝났다. 나머지는 데이터베이스와 도메인을 연결해주기만 하면 된다. 

이 글에서는 데이터베이스로 MySQL을 사용한다.

$ mysql -u "YOUR_ADMIN_USER" -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5340 to server version: 3.23.54
 
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
 
mysql> CREATE DATABASE "YOUR_DATABASE_NAME";
Query OK, 1 row affected (0.00 sec)
 
mysql> GRANT ALL PRIVILEGES ON "YOUR_DATABASE_NAME".* TO '"YOUR_WORDPRESS_USER"'@'"YOUR_HOST"'
    -> IDENTIFIED BY '"YOUR_PASSWORD"';
Query OK, 0 rows affected (0.00 sec)
  
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)

mysql> EXIT
Bye
$

wordpress로 사용할 계정을 만들었다면 도메인을 연결하면 된다.

이 글에선 apache를 이용한다.

cd /etc/apache2/sites-available/
sudo cp 000-default.conf "YOUR_DOMAIN.conf"
sudo vi "YOUR_DOMAIN.conf"
<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.

        ServerName "YOUR_DOMAIN (ex > minseo.siya.co.kr)"
        ServerAlias "YOUR_ALIAS_DOMAIN (ex > www.minseo.siya.co.kr)"

        ServerAdmin webmaster@localhost
        DocumentRoot "YOUR_WORDPRESS_DIR (ex > /home/minseo/www/html)"

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

 

이제 작성한 파일을 a2ensite를 이용하여 /etc/apache2/sites-enabled/ 로 옮긴다. 그 후 마지막으로 /etc/apache2/apache2.conf에서 디렉토리를 허가해주면 끝난다.

sudo a2ensite "YOUR_DOMAIN"
sudo vi /etc/apache2/apache2.conf

파일 중간에 추가해주면 된다.

<Directory "YOUR_WORDPRESS_DIR">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

다 끝났다. 마지막으로 apache를 재시작하면 된다.

sudo service apache2 restart

나머지는 설정한 도메인으로 들어가서 워드프레스를 구축하면 끝난다.

 

[pwnable] uaf

Mommy, what is Use After Free bug?

 

UAF(Use After Free)에 관한 문제이다.

코드를 까보자

#include <fcntl.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;

class Human{
private:
	virtual void give_shell(){
		system("/bin/sh");
	}
protected:
	int age;
	string name;
public:
	virtual void introduce(){
		cout << "My name is " << name << endl;
		cout << "I am " << age << " years old" << endl;
	}
};

class Man: public Human{
public:
	Man(string name, int age){
		this->name = name;
		this->age = age;
        }
        virtual void introduce(){
		Human::introduce();
                cout << "I am a nice guy!" << endl;
        }
};

class Woman: public Human{
public:
        Woman(string name, int age){
                this->name = name;
                this->age = age;
        }
        virtual void introduce(){
                Human::introduce();
                cout << "I am a cute girl!" << endl;
        }
};

int main(int argc, char* argv[]){
	Human* m = new Man("Jack", 25);
	Human* w = new Woman("Jill", 21);

	size_t len;
	char* data;
	unsigned int op;
	while(1){
		cout << "1. use\n2. after\n3. free\n";
		cin >> op;

		switch(op){
			case 1:
				m->introduce();
				w->introduce();
				break;
			case 2:
				len = atoi(argv[1]);
				data = new char[len];
				read(open(argv[2], O_RDONLY), data, len);
				cout << "your data is allocated" << endl;
				break;
			case 3:
				delete m;
				delete w;
				break;
			default:
				break;
		}
	}

	return 0;
}

 

virtual void give_shell(){
		system("/bin/sh");
	}

딱봐도 이 부분을 실행시켜야 할 것 같다.

그런데 코드에 저 부분을 부르는 곳이 없다.

뭔가 다른방법을 사용해야 할 것 같은데,

 

cout << "1. use\n2. after\n3. free\n";
cin >> op;

switch(op){
case 1:
	m->introduce();
	w->introduce();
	break;
case 2:
	len = atoi(argv[1]);
	data = new char[len];
	read(open(argv[2], O_RDONLY), data, len);
	cout << "your data is allocated" << endl;
	break;
case 3:
	delete m;
	delete w;
	break;
default:
	break;
}

 

메인함수에 use after free라고 대놓고 UAF를 써달라는 부분이 있다.

그럼 이제 UAF가 뭔지 알아보자.

UAF는 말 그대로 할당한 메모리 영역을 free한 다음 재사용할 때를 말한다.

 

 

case 3:
	delete m;
	delete w;
	break;

즉 여기서 m과 w를 해제하고,

 

case 1:
	m->introduce();
	w->introduce();
	break;

여기서 다시 사용하는게 UAF다.

보통의 경우 런타임 에러가 발생하겠지만, 모종의 방법으로 m과 w가 있었던 곳을 조작하면 개발자가 의도치 않은 기능을 수행할 수 있다.

 

size_t len;
char* data;
unsigned int op;
while(1){
	cout << "1. use\n2. after\n3. free\n";
	cin >> op;

	switch(op){
		case 1:
			m->introduce();
			w->introduce();
			break;
		case 2:
			len = atoi(argv[1]);
			data = new char[len];
			read(open(argv[2], O_RDONLY), data, len);
			cout << "your data is allocated" << endl;
			break;
		case 3:
			delete m;
			delete w;
			break;
		default:
			break;
	}
}

이걸 peda로 까보자

breakpoint는 main+265에 걸고 수행시켜본다.

RBX를 보면 0xbb6ca0 –> 0x401550 –> 0x40117a (<ZN5Human10give_shellEv>: push rbp)라는 부분이 보인다.

0x40117a를 실행 시킬 수 있다면 쉘을 딸 수 있을 것 같다.

계속해서 0x401550를 참조해보자

x/32x 0x401550과 x/32 *0x401550을 쳐보자

먼저 아래쪽을 보면(x/32x *0x401550)

give_shell의 주소는 0x40117a

introduce의 주소는 0x401192이다. (0x40119a-0x8)

 

다시 위쪽을 보면 0x401590에 0x40117a(give_shell)과 0x401192(introduce)가 나란히 위치한걸 볼 수 있다.

 

이제 페이로드를 작성해 case2를 통해 주소를 조작하여, introduce대신 give_shell을 실행하도록 하면 된다.

 

breakpoint 는 main+316이다.

우선 payload를 작성하기전에 파일이 메모리에 어떻게 들어가는지 알 필요가 있다.

파일을 하나 만들고, AAAABBBBCCCCDDDD라고 쓴 후에 저장한다.

그리고 peda로 들어가서 run 16 [filename]으로 실행한다.

먼저 3을 입력해 기존의 할당된 m, w를 해제시켜준다.

그 다음 2를 입력해 페이로드를 넣어본다.

 

 

main+419

 

 

그 다음 case 2로 들어가 할당을 해주고 값을 초기화 하는데, 적절한 방법을 통해 Human* -> introduce();를 Human -> give_shell();로 바꿔주면 클리어.

 

 

uaf@ubuntu:/tmp/uaf$ python ex.py
[+] Starting local process '/home/uaf/uaf': Done
[*] Switching to interactive mode
1. use
2. after
3. free
your data is allocated
1. use
2. after
3. free
your data is allocated
1. use
2. after
3. free
$ cat ~/flag
yay_f1ag_af*********

[pwnable] lotto

Mommy! I made a lotto program for my homework.
do you want to play?

 

코드부터 까보자.

 

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

unsigned char submit[6];

void play(){

	int i;
	printf("Submit your 6 lotto bytes : ");
	fflush(stdout);

	int r;
	r = read(0, submit, 6);

	printf("Lotto Start!\n");
	//sleep(1);

	// generate lotto numbers
	int fd = open("/dev/urandom", O_RDONLY);
	if(fd==-1){
		printf("error. tell admin\n");
		exit(-1);
	}
	unsigned char lotto[6];
	if(read(fd, lotto, 6) != 6){
		printf("error2. tell admin\n");
		exit(-1);
	}
	for(i=0; i<6; i++){
		lotto[i] = (lotto[i] % 45) + 1;		// 1 ~ 45
	}
	close(fd);

	// calculate lotto score
	int match = 0, j = 0;
	for(i=0; i<6; i++){
		for(j=0; j<6; j++){
			if(lotto[i] == submit[j]){
				match++;
			}
		}
	}

	// win!
	if(match == 6){
		system("/bin/cat flag");
	}
	else{
		printf("bad luck...\n");
	}

}

void help(){
	printf("- nLotto Rule -\n");
	printf("nlotto is consisted with 6 random natural numbers less than 46\n");
	printf("your goal is to match lotto numbers as many as you can\n");
	printf("if you win lottery for *1st place*, you will get reward\n");
	printf("for more details, follow the link below\n");
	printf("http://www.nlotto.co.kr/counsel.do?method=playerGuide#buying_guide01\n\n");
	printf("mathematical chance to win this game is known to be 1/8145060.\n");
}

int main(int argc, char* argv[]){

	// menu
	unsigned int menu;

	while(1){

		printf("- Select Menu -\n");
		printf("1. Play Lotto\n");
		printf("2. Help\n");
		printf("3. Exit\n");

		scanf("%d", &menu);

		switch(menu){
			case 1:
				play();
				break;
			case 2:
				help();
				break;
			case 3:
				printf("bye\n");
				return 0;
			default:
				printf("invalid menu\n");
				break;
		}
	}
	return 0;
}

 

2점짜리라 그런지 문제가 굉장히 쉽다.

 

	// calculate lotto score
	int match = 0, j = 0;
	for(i=0; i<6; i++){
		for(j=0; j<6; j++){
			if(lotto[i] == submit[j]){
				match++;
			}
		}
	}

	// win!
	if(match == 6){
		system("/bin/cat flag");
	}
	else{
		printf("bad luck...\n");
	}

play()안의 정답 판정을 하는 부분의 알고리즘이 잘못되었다.

이렇게 코드를 짜면 중복체크가 되어버린다.

예를들면 당첨번호가 1, 2, 3, 4, 5, 6이고 내가 입력한게 1, 1, 1, 1, 1, 1이면 match가 6으로  정답이 되어버린다.

 

그럼 남은건 하나로 찍어서 2/15의 확률을 뚫으면 된다.

그런데 문제가 있다.

 

r = read(0, submit, 6);

입력을 받는 부분이 read라서 0~9를 입력하면 48~57의 값이 들어가버린다.

즉 ASCII코드 값으로 1~45의 값을 넣어줘야 한다.

제어문자는 입력하기 귀찮으므로 여기서는 ASCII코드 42값인 *을 사용한다.

 

lotto@ubuntu:~$ ./lotto
- Select Menu -
1. Play Lotto
2. Help
3. Exit
Submit your 6 lotto bytes : ******
Lotto Start!
bad luck...
- Select Menu -
1. Play Lotto
2. Help
3. Exit
Submit your 6 lotto bytes : *******
Lotto Start!
sorry mom... I FORGOT to check du**************

 

[pwnable] blackjack

pwnable에는 재미있는 문제가 많은 것 같다.

특히 게임 형태로 내는 문제가 재밌는데, 오늘은 그 중 가장 쉬운 두 문제를 포스팅할까 한다.

 

Hey! check out this C implementation of blackjack game!
I found it online
* http://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html

I like to give my flags to millionares.
how much money you got?

 

첫번째는 blackjack문제이다.

보다시피 $1,000,000을 벌면 flag값을 준다는 내용이다.

 

물론 블랙잭 게임을 좋아하면 순수 게임만으로 풀리지만, 취약점을 찾는 것이 목표이므로 코드를 보겠다.

 

// Programmer: Vladislav Shulman
// Final Project
// Blackjack
 
// Feel free to use any and all parts of this program and claim it as your own work
 
//FINAL DRAFT
 
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>                //Used for srand((unsigned) time(NULL)) command
#include <process.h>             //Used for system("cls") command
 
#define spade 06                 //Used to print spade symbol
#define club 05                  //Used to print club symbol
#define diamond 04               //Used to print diamond symbol
#define heart 03                 //Used to print heart symbol
#define RESULTS "Blackjack.txt"  //File name is Blackjack
 
//Global Variables
int k;
int l;
int d;
int won;
int loss;
int cash = 500;
int bet;
int random_card;
int player_total=0;
int dealer_total;
 
//Function Prototypes
int clubcard();      //Displays Club Card Image
int diamondcard();   //Displays Diamond Card Image
int heartcard();     //Displays Heart Card Image
int spadecard();     //Displays Spade Card Image
int randcard();      //Generates random card
int betting();       //Asks user amount to bet
void asktitle();     //Asks user to continue
void rules();        //Prints "Rules of Vlad's Blackjack" menu
void play();         //Plays game
void dealer();       //Function to play for dealer AI
void stay();         //Function for when user selects 'Stay'
void cash_test();    //Test for if user has cash remaining in purse
void askover();      //Asks if user wants to continue playing
void fileresults();  //Prints results into Blackjack.txt file in program directory
 
//Main Function
int main(void)
{
    int choice1;
    printf("\n");
    printf("\n");
    printf("\n");
    printf("\n              222                111                            ");
    printf("\n            222 222            11111                              ");
    printf("\n           222   222          11 111                            "); 
    printf("\n                222              111                               "); 
    printf("\n               222               111                           ");   
    printf("\n");
    printf("\n%c%c%c%c%c     %c%c            %c%c         %c%c%c%c%c    %c    %c                ", club, club, club, club, club, spade, spade, diamond, diamond, heart, heart, heart, heart, heart, club, club);  
    printf("\n%c    %c    %c%c           %c  %c       %c     %c   %c   %c              ", club, club, spade, spade, diamond, diamond, heart, heart, club, club);            
    printf("\n%c    %c    %c%c          %c    %c     %c          %c  %c               ", club, club, spade, spade, diamond, diamond, heart, club, club);                        
    printf("\n%c%c%c%c%c     %c%c          %c %c%c %c     %c          %c %c              ", club, club, club, club, club, spade, spade, diamond, diamond, diamond, diamond, heart, club, club);      
    printf("\n%c    %c    %c%c         %c %c%c%c%c %c    %c          %c%c %c             ", club, club, spade, spade, diamond, diamond, diamond, diamond, diamond, diamond, heart, club, club, club);                       
    printf("\n%c     %c   %c%c         %c      %c    %c          %c   %c               ", club, club, spade, spade, diamond, diamond, heart, club, club);                                         
    printf("\n%c     %c   %c%c        %c        %c    %c     %c   %c    %c             ", club, club, spade, spade, diamond, diamond, heart, heart, club, club);                                                            
    printf("\n%c%c%c%c%c%c    %c%c%c%c%c%c%c   %c        %c     %c%c%c%c%c    %c     %c            ", club, club, club, club, club, club, spade, spade, spade, spade, spade, spade, spade, diamond, diamond, heart, heart, heart, heart, heart, club, club);                                                                                     
    printf("\n");     
    printf("\n                        21                                   ");
     
    printf("\n     %c%c%c%c%c%c%c%c      %c%c         %c%c%c%c%c    %c    %c                ", diamond, diamond, diamond, diamond, diamond, diamond, diamond, diamond, heart, heart, club, club, club, club, club, spade, spade);                     
    printf("\n        %c%c        %c  %c       %c     %c   %c   %c              ", diamond, diamond, heart, heart, club, club, spade, spade);                                      
    printf("\n        %c%c       %c    %c     %c          %c  %c               ", diamond, diamond, heart, heart, club, spade, spade);                                           
    printf("\n        %c%c       %c %c%c %c     %c          %c %c              ", diamond, diamond, heart, heart, heart, heart, club, spade, spade);                                     
    printf("\n        %c%c      %c %c%c%c%c %c    %c          %c%c %c             ", diamond, diamond, heart, heart, heart, heart, heart, heart, club, spade, spade, spade);                                                
    printf("\n        %c%c      %c      %c    %c          %c   %c               ", diamond, diamond, heart, heart, club, spade, spade);                                                                               
    printf("\n     %c  %c%c     %c        %c    %c     %c   %c    %c             ", diamond, diamond, diamond, heart, heart, club, spade, spade);                                                                                                               
    printf("\n      %c%c%c      %c        %c     %c%c%c%c%c    %c     %c            ", diamond, diamond, diamond, heart, heart, club, club, club, club, club, spade, spade);                                                                                                                                        
    printf("\n");  
    printf("\n         222                     111                         ");
    printf("\n        222                      111                         ");
    printf("\n       222                       111                         ");
    printf("\n      222222222222222      111111111111111                       ");
    printf("\n      2222222222222222    11111111111111111                         ");
    printf("\n");
    printf("\n");
     
    asktitle();
     
    printf("\n");
    printf("\n");
    system("pause");
    return(0);
} //end program
 
void asktitle() // Function for asking player if they want to continue
{
    char choice1;
    int choice2;
     
     printf("\n                 Are You Ready?");
     printf("\n                ----------------");
     printf("\n                      (Y/N)\n                        ");
     scanf("\n%c",&choice1);
 
    while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered
    {                                                                           
        printf("\n");
        printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");
        scanf("%c",&choice1);
    }
 
 
    if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue. Prints menu.
    { 
            system("cls");
            printf("\nEnter 1 to Begin the Greatest Game Ever Played.");
            printf("\nEnter 2 to See a Complete Listing of Rules.");
            printf("\nEnter 3 to Exit Game. (Not Recommended)");
            printf("\nChoice: ");
            scanf("%d", &choice2); // Prompts user for choice
            if((choice2<1) || (choice2>3)) // If invalid choice entered
            {
                printf("\nIncorrect Choice. Please enter 1, 2 or 3\n");
                scanf("%d", &choice2);
            }
            switch(choice2) // Switch case for different choices
            {   
                case 1: // Case to begin game
                   system("cls");
                    
                   play();
                                       
                   break;
                    
                case 2: // Case to see rules
                   system("cls");
                   rules();
                   break;
                    
                case 3: // Case to exit game
                   printf("\nYour day could have been perfect.");
                   printf("\nHave an almost perfect day!\n\n");
                   system("pause");
                   exit(0);
                   break;
                    
                default:
                   printf("\nInvalid Input");
            } // End switch case
    } // End if loop
    
             
 
    else if((choice1 == 'N') || (choice1 == 'n')) // If no, exit program
    {
        printf("\nYour day could have been perfect.");
        printf("\nHave an almost perfect day!\n\n");
        system("pause");
        exit(0);
    }
     
    return;
} // End function
 
void rules() //Prints "Rules of Vlad's Blackjack" list
{
     char choice1;
     int choice2;
      
     printf("\n           RULES of VLAD's BLACKJACK");
     printf("\n          ---------------------------");
     printf("\nI.");
     printf("\n     Thou shalt not question the odds of this game.");
     printf("\n      %c This program generates cards at random.", spade);
     printf("\n      %c If you keep losing, you are very unlucky!\n", diamond);
      
     printf("\nII.");
     printf("\n     Each card has a value.");
     printf("\n      %c Number cards 1 to 10 hold a value of their number.", spade);
     printf("\n      %c J, Q, and K cards hold a value of 10.", diamond);
     printf("\n      %c Ace cards hold a value of 11", club);
     printf("\n     The goal of this game is to reach a card value total of 21.\n");
      
     printf("\nIII.");
     printf("\n     After the dealing of the first two cards, YOU must decide whether to HIT or STAY.");
     printf("\n      %c Staying will keep you safe, hitting will add a card.", spade);
     printf("\n     Because you are competing against the dealer, you must beat his hand.");
     printf("\n     BUT BEWARE!.");
     printf("\n      %c If your total goes over 21, you will LOSE!.", diamond);
     printf("\n     But the world is not over, because you can always play again.\n");
     printf("\n%c%c%c YOUR RESULTS ARE RECORDED AND FOUND IN SAME FOLDER AS PROGRAM %c%c%c\n", spade, heart, club, club, heart, spade);
     printf("\nWould you like to go the previous screen? (I will not take NO for an answer)");
     printf("\n                  (Y/N)\n                    ");
     scanf("\n%c",&choice1);
      
     while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered
    {                                                                           
        printf("\n");
        printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");
        scanf("%c",&choice1);
    }
 
 
    if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue. Prints menu.
    { 
            system("cls");
            asktitle();
    } // End if loop
    
             
 
    else if((choice1 == 'N') || (choice1 == 'n')) // If no, convinces user to enter yes
    {
        system("cls");
        printf("\n                 I told you so.\n");
        asktitle();
    }
     
    return;
} // End function
 
int clubcard() //Displays Club Card Image
{
     
     
    srand((unsigned) time(NULL)); //Generates random seed for rand() function
    k=rand()%13+1;
     
    if(k<=9) //If random number is 9 or less, print card with that number
    {
    //Club Card
    printf("-------\n");
    printf("|%c    |\n", club);
    printf("|  %d  |\n", k);
    printf("|    %c|\n", club);
    printf("-------\n");
    }
     
     
    if(k==10) //If random number is 10, print card with J (Jack) on face
    {
    //Club Card
    printf("-------\n");
    printf("|%c    |\n", club);
    printf("|  J  |\n");
    printf("|    %c|\n", club);
    printf("-------\n");
    }
     
     
    if(k==11) //If random number is 11, print card with A (Ace) on face
    {
    //Club Card
    printf("-------\n");
    printf("|%c    |\n", club);
    printf("|  A  |\n");
    printf("|    %c|\n", club);
    printf("-------\n");
    if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total
         {
             k=11;
         }
          
         else
         {
 
             k=1;
         }
    }
     
     
    if(k==12) //If random number is 12, print card with Q (Queen) on face
    {
    //Club Card
    printf("-------\n");
    printf("|%c    |\n", club);
    printf("|  Q  |\n");
    printf("|    %c|\n", club);
    printf("-------\n");
    k=10; //Set card value to 10
    }
     
     
    if(k==13) //If random number is 13, print card with K (King) on face
    {
    //Club Card
    printf("-------\n");
    printf("|%c    |\n", club);
    printf("|  K  |\n");
    printf("|    %c|\n", club);
    printf("-------\n");
    k=10; //Set card value to 10
    }
    return k;           
}// End function
 
int diamondcard() //Displays Diamond Card Image
{
     
     
    srand((unsigned) time(NULL)); //Generates random seed for rand() function
    k=rand()%13+1;
     
    if(k<=9) //If random number is 9 or less, print card with that number
    {
    //Diamond Card
    printf("-------\n");
    printf("|%c    |\n", diamond);
    printf("|  %d  |\n", k);
    printf("|    %c|\n", diamond);
    printf("-------\n");
    }
     
    if(k==10) //If random number is 10, print card with J (Jack) on face
    {
    //Diamond Card
    printf("-------\n");
    printf("|%c    |\n", diamond);
    printf("|  J  |\n");
    printf("|    %c|\n", diamond);
    printf("-------\n");
    }
     
    if(k==11) //If random number is 11, print card with A (Ace) on face
    {
    //Diamond Card
    printf("-------\n");
    printf("|%c    |\n", diamond);
    printf("|  A  |\n");
    printf("|    %c|\n", diamond);
    printf("-------\n");
    if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total
         {
             k=11;
         }
          
         else
         {
             k=1;
         }
    }
     
    if(k==12) //If random number is 12, print card with Q (Queen) on face
    {
    //Diamond Card
    printf("-------\n");
    printf("|%c    |\n", diamond);
    printf("|  Q  |\n");
    printf("|    %c|\n", diamond);
    printf("-------\n");
    k=10; //Set card value to 10
    }
     
    if(k==13) //If random number is 13, print card with K (King) on face
    {
    //Diamond Card
    printf("-------\n");
    printf("|%c    |\n", diamond);
    printf("|  K  |\n");
    printf("|    %c|\n", diamond);
    printf("-------\n");
    k=10; //Set card value to 10
    }
    return k;
}// End function
 
int heartcard() //Displays Heart Card Image
{
     
     
    srand((unsigned) time(NULL)); //Generates random seed for rand() function
    k=rand()%13+1;
     
    if(k<=9) //If random number is 9 or less, print card with that number
    {
    //Heart Card
    printf("-------\n");
    printf("|%c    |\n", heart); 
    printf("|  %d  |\n", k);
    printf("|    %c|\n", heart);
    printf("-------\n");
    }
     
    if(k==10) //If random number is 10, print card with J (Jack) on face
    {
    //Heart Card
    printf("-------\n");
    printf("|%c    |\n", heart);
    printf("|  J  |\n");
    printf("|    %c|\n", heart);
    printf("-------\n");
    }
     
    if(k==11) //If random number is 11, print card with A (Ace) on face
    {
    //Heart Card
    printf("-------\n");
    printf("|%c    |\n", heart);
    printf("|  A  |\n");
    printf("|    %c|\n", heart);
    printf("-------\n");
    if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total
         {
             k=11;
         }
          
         else
         {
             k=1;
         }
    }
     
    if(k==12) //If random number is 12, print card with Q (Queen) on face
    {
    //Heart Card
    printf("-------\n");
    printf("|%c    |\n", heart);
    printf("|  Q  |\n");
    printf("|    %c|\n", heart);
    printf("-------\n");
    k=10; //Set card value to 10
    }
     
    if(k==13) //If random number is 13, print card with K (King) on face
    {
    //Heart Card
    printf("-------\n");
    printf("|%c    |\n", heart);
    printf("|  K  |\n");
    printf("|    %c|\n", heart);
    printf("-------\n");
    k=10; //Set card value to 10
    }
    return k;
} // End Function
 
int spadecard() //Displays Spade Card Image
{
     
     
    srand((unsigned) time(NULL)); //Generates random seed for rand() function
    k=rand()%13+1;
     
    if(k<=9) //If random number is 9 or less, print card with that number
    {
    //Spade Card
    printf("-------\n");
    printf("|%c    |\n", spade);
    printf("|  %d  |\n", k);
    printf("|    %c|\n", spade);
    printf("-------\n");
    }
     
    if(k==10) //If random number is 10, print card with J (Jack) on face
    {
    //Spade Card
    printf("-------\n");
    printf("|%c    |\n", spade);
    printf("|  J  |\n");
    printf("|    %c|\n", spade);
    printf("-------\n");
    }
     
    if(k==11) //If random number is 11, print card with A (Ace) on face
    {
    //Spade Card
    printf("-------\n");
    printf("|%c    |\n", spade);
    printf("|  A  |\n");
    printf("|    %c|\n", spade);
    printf("-------\n");
    if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total
         {
             k=11;
         }
          
         else
         {
             k=1;
         }
    }
     
    if(k==12) //If random number is 12, print card with Q (Queen) on face
    {
    //Spade Card
    printf("-------\n");
    printf("|%c    |\n", spade);
    printf("|  Q  |\n");
    printf("|    %c|\n", spade);
    printf("-------\n");
    k=10; //Set card value to 10
    }
     
    if(k==13) //If random number is 13, print card with K (King) on face
    {
    //Spade Card
    printf("-------\n");
    printf("|%c    |\n", spade);
    printf("|  K  |\n");
    printf("|    %c|\n", spade);
    printf("-------\n");
    k=10; //Set card value to 10
    }
    return k;
} // End Function
 
int randcard() //Generates random card
{
      
                
     srand((unsigned) time(NULL)); //Generates random seed for rand() function
     random_card = rand()%4+1;
      
     if(random_card==1)
     {   
         clubcard();
         l=k;
     }
      
     if(random_card==2)
     {
         diamondcard();
         l=k;
     }
      
     if(random_card==3)
     {
         heartcard();
         l=k;
     }
          
     if(random_card==4)
     {
         spadecard();
         l=k;
     }    
     return l;
} // End Function   
 
void play() //Plays game
{
      
     int p=0; // holds value of player_total
     int i=1; // counter for asking user to hold or stay (aka game turns)
     char choice3;
      
     cash = cash;
     cash_test();
     printf("\nCash: $%d\n",cash); //Prints amount of cash user has
     randcard(); //Generates random card
     player_total = p + l; //Computes player total
     p = player_total;
     printf("\nYour Total is %d\n", p); //Prints player total
     dealer(); //Computes and prints dealer total
     betting(); //Prompts user to enter bet amount
        
     while(i<=21) //While loop used to keep asking user to hit or stay at most twenty-one times
                  //  because there is a chance user can generate twenty-one consecutive 1's
     {
         if(p==21) //If user total is 21, win
         {
             printf("\nUnbelievable! You Win!\n");
             won = won+1;
             cash = cash+bet;
             printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
             dealer_total=0;
             askover();
         }
      
         if(p>21) //If player total is over 21, loss
         {
             printf("\nWoah Buddy, You Went WAY over.\n");
             loss = loss+1;
             cash = cash - bet;
             printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
             dealer_total=0;
             askover();
         }
      
         if(p<=21) //If player total is less than 21, ask to hit or stay
         {         
             printf("\n\nWould You Like to Hit or Stay?");
              
             scanf("%c", &choice3);
             while((choice3!='H') && (choice3!='h') && (choice3!='S') && (choice3!='s')) // If invalid choice entered
             {                                                                           
                 printf("\n");
                 printf("Please Enter H to Hit or S to Stay.\n");
                 scanf("%c",&choice3);
             }
 
 
             if((choice3=='H') || (choice3=='h')) // If Hit, continues
             { 
                 randcard();
                 player_total = p + l;
                 p = player_total;
                 printf("\nYour Total is %d\n", p);
                 dealer();
                  if(dealer_total==21) //Is dealer total is 21, loss
                  {
                      printf("\nDealer Has the Better Hand. You Lose.\n");
                      loss = loss+1;
                      cash = cash - bet;
                      printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
                      dealer_total=0;
                      askover();
                  } 
      
                  if(dealer_total>21) //If dealer total is over 21, win
                  {                      
                      printf("\nDealer Has Went Over!. You Win!\n");
                      won = won+1;
                      cash = cash+bet;
                      printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
                      dealer_total=0;
                      askover();
                  }
             }
             if((choice3=='S') || (choice3=='s')) // If Stay, does not continue
             {
                printf("\nYou Have Chosen to Stay at %d. Wise Decision!\n", player_total);
                stay();
             }
          }
             i++; //While player total and dealer total are less than 21, re-do while loop 
     } // End While Loop
} // End Function
 
void dealer() //Function to play for dealer AI
{
     int z;
      
     if(dealer_total<17)
     {
      srand((unsigned) time(NULL) + 1); //Generates random seed for rand() function
      z=rand()%13+1;
      if(z<=10) //If random number generated is 10 or less, keep that value
      {
         d=z;
          
      }
      
      if(z>11) //If random number generated is more than 11, change value to 10
      {
         d=10;
      }
      
      if(z==11) //If random number is 11(Ace), change value to 11 or 1 depending on dealer total
      {
         if(dealer_total<=10)
         {
             d=11;
         }
          
         else
         {
             d=1;
         }
      }
     dealer_total = dealer_total + d;
     }
           
     printf("\nThe Dealer Has a Total of %d", dealer_total); //Prints dealer total
      
} // End Function 
 
void stay() //Function for when user selects 'Stay'
{
     dealer(); //If stay selected, dealer continues going
     if(dealer_total>=17)
     {
      if(player_total>=dealer_total) //If player's total is more than dealer's total, win
      {
         printf("\nUnbelievable! You Win!\n");
         won = won+1;
         cash = cash+bet;
         printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
         dealer_total=0;
         askover();
      }
      if(player_total<dealer_total) //If player's total is less than dealer's total, loss
      {
         printf("\nDealer Has the Better Hand. You Lose.\n");
         loss = loss+1;
         cash = cash - bet;
         printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
         dealer_total=0;
         askover();
      }
      if(dealer_total>21) //If dealer's total is more than 21, win
      {
         printf("\nUnbelievable! You Win!\n");
         won = won+1;
         cash = cash+bet;
         printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
         dealer_total=0;
         askover();
      }
     }
     else
     {
         stay();
     }
      
} // End Function
 
void cash_test() //Test for if user has cash remaining in purse
{
     if (cash <= 0) //Once user has zero remaining cash, game ends and prompts user to play again
     {
        printf("You Are Bankrupt. Game Over");
        cash = 500;
        askover();
     }
} // End Function
 
int betting() //Asks user amount to bet
{
 printf("\n\nEnter Bet: $");
 scanf("%d", &bet);
 
 if (bet > cash) //If player tries to bet more money than player has
 {
        printf("\nYou cannot bet more money than you have.");
        printf("\nEnter Bet: ");
        scanf("%d", &bet);
        return bet;
 }
 else return bet;
} // End Function
 
void askover() // Function for asking player if they want to play again
{
    char choice1;
         
     printf("\nWould You Like To Play Again?");
     printf("\nPlease Enter Y for Yes or N for No\n");
     scanf("\n%c",&choice1);
 
    while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered
    {                                                                           
        printf("\n");
        printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");
        scanf("%c",&choice1);
    }
 
 
    if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue.
    { 
            system("cls");
            play();
    }
  
    else if((choice1 == 'N') || (choice1 == 'n')) // If no, exit program
    {
        fileresults();
        printf("\nBYE!!!!\n\n");
        system("pause");
        exit(0);
    }
    return;
} // End function
 
void fileresults() //Prints results into Blackjack.txt file in program directory
{
    FILE *fpresults; //File pointer is fpresults
    fpresults = fopen(RESULTS, "w"); //Creates file and writes into it
    if(fpresults == NULL) // what to do if file missing from directory
    {
               printf("\nError: File Missing\n");
               system("pause");
               exit(1);
    }
    else
    {     
     fprintf(fpresults,"\n\t RESULTS");
     fprintf(fpresults,"\n\t---------\n");
     fprintf(fpresults,"\nYou Have Won %d Times\n", won);
     fprintf(fpresults,"\nYou Have Lost %d Times\n", loss);
     fprintf(fpresults,"\nKeep Playing and Set an All-Time Record!");
    } 
     fclose(fpresults);
     return;
} // End Function

 

길다.

취약점과 별 관련이 없어보이는 부분을 제거해보겠다.

int main(void){
    asktitle();
}
 
void asktitle() // Function for asking player if they want to continue
{
    char choice1;
    int choice2;
     
     printf("\n                 Are You Ready?");
     scanf("\n%c",&choice1);
 
    while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')){                                                                           
        printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");
        scanf("%c",&choice1);
    }
 
 
    if((choice1 == 'Y') || (choice1 == 'y')){ 
            printf("\nChoice: ");
            scanf("%d", &choice2); // Prompts user for choice
            if((choice2<1) || (choice2>3)) // If invalid choice entered
            {
                printf("\nIncorrect Choice. Please enter 1, 2 or 3\n");
                scanf("%d", &choice2);
            }
            switch(choice2) // Switch case for different choices
            {   
                case 1: // Case to begin game
                   play();
                   break;
                case 2: // Case to see rules
                   rules();
                   break;
                case 3: // Case to exit game
                   exit(0);
                   break;
                default:
                   printf("\nInvalid Input");
            } // End switch case
    } // End if loop
    
             
 
    else if((choice1 == 'N') || (choice1 == 'n')){
        exit(0);
    }
     
    return;
} // End function
 
int randcard() //Generates random card
{      
     srand((unsigned) time(NULL)); //Generates random seed for rand() function
     random_card = rand()%4+1;
      
     return l;
} // End Function   
 
void play() //Plays game
{      
     cash_test();
     randcard(); //Generates random card
     dealer(); //Computes and prints dealer total
     betting(); //Prompts user to enter bet amount
        
     while(i<=21) //While loop used to keep asking user to hit or stay at most twenty-one times
                  //  because there is a chance user can generate twenty-one consecutive 1's
     {
         if(p==21) //If user total is 21, win
         {
             printf("\nUnbelievable! You Win!\n");
             won = won+1;
             cash = cash+bet;
             printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
             dealer_total=0;
             askover();
         }
      
         if(p>21) //If player total is over 21, loss
         {
             printf("\nWoah Buddy, You Went WAY over.\n");
             loss = loss+1;
             cash = cash - bet;
             printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
             dealer_total=0;
             askover();
         }
      
         if(p<=21) //If player total is less than 21, ask to hit or stay
         {         
             printf("\n\nWould You Like to Hit or Stay?");
              
             scanf("%c", &choice3);
             while((choice3!='H') && (choice3!='h') && (choice3!='S') && (choice3!='s')) // If invalid choice entered
             {                                                                           
                 printf("\n");
                 printf("Please Enter H to Hit or S to Stay.\n");
                 scanf("%c",&choice3);
             }
 
 
             if((choice3=='H') || (choice3=='h')) // If Hit, continues
             { 
                 randcard();
                 player_total = p + l;
                 p = player_total;
                 printf("\nYour Total is %d\n", p);
                 dealer();
                  if(dealer_total==21) //Is dealer total is 21, loss
                  {
                      printf("\nDealer Has the Better Hand. You Lose.\n");
                      loss = loss+1;
                      cash = cash - bet;
                      printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
                      dealer_total=0;
                      askover();
                  } 
      
                  if(dealer_total>21) //If dealer total is over 21, win
                  {                      
                      printf("\nDealer Has Went Over!. You Win!\n");
                      won = won+1;
                      cash = cash+bet;
                      printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
                      dealer_total=0;
                      askover();
                  }
             }
             if((choice3=='S') || (choice3=='s')) // If Stay, does not continue
             {
                printf("\nYou Have Chosen to Stay at %d. Wise Decision!\n", player_total);
                stay();
             }
          }
             i++; //While player total and dealer total are less than 21, re-do while loop 
     } // End While Loop
} // End Function
 
void dealer() //Function to play for dealer AI
{
     int z;
      
     if(dealer_total<17)
     {
      srand((unsigned) time(NULL) + 1); //Generates random seed for rand() function
      z=rand()%13+1;
      if(z<=10) //If random number generated is 10 or less, keep that value
      {
         d=z;
          
      }
      
      if(z>11) //If random number generated is more than 11, change value to 10
      {
         d=10;
      }
      
      if(z==11) //If random number is 11(Ace), change value to 11 or 1 depending on dealer total
      {
         if(dealer_total<=10)
         {
             d=11;
         }
          
         else
         {
             d=1;
         }
      }
     dealer_total = dealer_total + d;
     }
           
     printf("\nThe Dealer Has a Total of %d", dealer_total); //Prints dealer total
      
} // End Function 
 
void stay() //Function for when user selects 'Stay'
{
     dealer(); //If stay selected, dealer continues going
     if(dealer_total>=17)
     {
      if(player_total>=dealer_total) //If player's total is more than dealer's total, win
      {
         printf("\nUnbelievable! You Win!\n");
         won = won+1;
         cash = cash+bet;
         printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
         dealer_total=0;
         askover();
      }
      if(player_total<dealer_total) //If player's total is less than dealer's total, loss
      {
         printf("\nDealer Has the Better Hand. You Lose.\n");
         loss = loss+1;
         cash = cash - bet;
         printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
         dealer_total=0;
         askover();
      }
      if(dealer_total>21) //If dealer's total is more than 21, win
      {
         printf("\nUnbelievable! You Win!\n");
         won = won+1;
         cash = cash+bet;
         printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
         dealer_total=0;
         askover();
      }
     }
     else
     {
         stay();
     }
      
} // End Function
 
void cash_test() //Test for if user has cash remaining in purse
{
     if (cash <= 0) //Once user has zero remaining cash, game ends and prompts user to play again
     {
        printf("You Are Bankrupt. Game Over");
        cash = 500;
        askover();
     }
} // End Function
 
int betting() //Asks user amount to bet
{
 printf("\n\nEnter Bet: $");
 scanf("%d", &bet);
 
 if (bet > cash) //If player tries to bet more money than player has
 {
        printf("\nYou cannot bet more money than you have.");
        printf("\nEnter Bet: ");
        scanf("%d", &bet);
        return bet;
 }
 else return bet;
} // End Function
 
void askover() // Function for asking player if they want to play again
{
    char choice1;
         
     printf("\nWould You Like To Play Again?");
     printf("\nPlease Enter Y for Yes or N for No\n");
     scanf("\n%c",&choice1);
 
    while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered
    {                                                                           
        printf("\n");
        printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");
        scanf("%c",&choice1);
    }
 
 
    if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue.
    { 
            system("cls");
            play();
    }
  
    else if((choice1 == 'N') || (choice1 == 'n')) // If no, exit program
    {
        fileresults();
        printf("\nBYE!!!!\n\n");
        system("pause");
        exit(0);
    }
    return;
} // End function
 
void fileresults(){
    FILE *fpresults; //File pointer is fpresults
    fpresults = fopen(RESULTS, "w"); //Creates file and writes into it
    if(fpresults == NULL) // what to do if file missing from directory
    {
               printf("\nError: File Missing\n");
               system("pause");
               exit(1);
    } 
     fclose(fpresults);
     return;
} // End Function

 

간단하게 요약하면 게임 시작을 하면 패배조건을 체크(cash_test)를 하고 카드를 섞은다음(randcard) 딜러가 한장 뽑고(dealer) 유저가 배팅을 한 다음(betting) 서로 게임을 진행한다.

 

이제 하나하나 분석해보자. 먼저 randcard 함수를 보면

srand((unsigned) time(NULL));

의 존재때문에 [pwnable] random 문제 때처럼 랜덤값을 이용할 순 없다.

 

다음 dealer를 보면 합이 17 이상부터는 카드를 절대 뽑지 않는다는걸 알 수 있다.

그럼 상대가 17 이상이고 내가 그 수 보다 같거나 클 때(stay) 스테이를 하면 무조건 이긴다는걸 알 수 있다.

그런데 이거가지고 100만달러를 벌기엔 많이 부족해보인다.

 

그 다음 betting을 보자

int betting() //Asks user amount to bet
{
 printf("\n\nEnter Bet: $");
 scanf("%d", &bet);
 
 if (bet > cash) //If player tries to bet more money than player has
 {
        printf("\nYou cannot bet more money than you have.");
        printf("\nEnter Bet: ");
        scanf("%d", &bet);
        return bet;
 }
 else return bet;
} // End Function

 

?? 뭔가 예외처리를 한거같긴 한데 while이 아니라 if다.

그럼 두 번째부터는 예외처리가 되지 않는다는거다.

즉, 내 소지금에 상관없이 배팅을 무한대로 할 수 있다는 것이다.

 

그럼 이제 배팅금액을 $1,000,000 이상으로 잡고 이길때까지 몇 판만 해주면 된다.

 

Cash: $500
-------
|C    |
|  2  |
|    C|
-------

Your Total is 2

The Dealer Has a Total of 8

Enter Bet: $10000000

You cannot bet more money than you have.
Enter Bet: 10000000


Would You Like to Hit or Stay?
Please Enter H to Hit or S to Stay.
H
-------
|C    |
|  5  |
|    C|
-------

Your Total is 7

The Dealer Has a Total of 12

Would You Like to Hit or Stay?
Please Enter H to Hit or S to Stay.
H
-------
|S    |
|  Q  |
|    S|
-------

Your Total is 17

The Dealer Has a Total of 17

Would You Like to Hit or Stay?
Please Enter H to Hit or S to Stay.
S

You Have Chosen to Stay at 17. Wise Decision!

The Dealer Has a Total of 17
Unbelievable! You Win!

You have 1 Wins and 0 Losses. Awesome!

Would You Like To Play Again?
Please Enter Y for Yes or N for No
Y

YaY_I_AM_A_MILL***********

 

[pwnable] fd

Mommy! what is a file descriptor in Linux?

 

리눅스 file descriptor에 대해 이해하고 있는지를 묻는 문제이다.

ssh fd@pwnable.kr -p2222에 접속하여 ls -l를 쳐보면

-r-sr-x--- 1 fd_pwn fd 7322 Jun 11 2014 fd
-rw-r--r-- 1 root root 418 Jun 11 2014 fd.c
-r--r----- 1 fd_pwn root 50 Jun 11 2014 flag

 

위와 같은 내용을 확인할 수 있다.

우리가 원하는건 flag인데 권한이 없어서 볼 수가 없다.

그럼 열어볼 수 있는 fd.c를 열어보자.

 

cat fd.c을 치면 아래와 같은 내용이 나온다.

 

int main(int argc, char* argv[], char* envp[]){
	if(argc<2){
		printf("pass argv[1] a number\n");
		return 0;
	}
	int fd = atoi( argv[1] ) - 0x1234;
	int len = 0;
	len = read(fd, buf, 32);
	if(!strcmp("LETMEWIN\n", buf)){
		printf("good job :)\n");
		system("/bin/cat flag");
		exit(0);
	}
	printf("learn about Linux file IO\n");
	return 0;

}

 

 

위의 코드중에 len = read(fd, buf, 32);를 제외한 나머지 코드를 이해하지 못하는 사람이라면 C를 먼저 공부하고 오는걸 추천한다.

위 코드를 정리하면 buf의 내용이 “LETMEWIN\n”이면 flag의 내용을 보여주는 프로그램이란걸 알 수 있다.

그럼 buf에 “LETMEWIN\n”을 담으려면 어떻게 해야할까?

우리는 여기서 file descriptor에 대해 공부할 필요가 있다.

http://unabated.tistory.com/entry/%ED%8C%8C%EC%9D%BC-%EB%94%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%84%B0

 

결론을 말하자면 fd의 값 중 0, 1, 2는 미리 예약이 되어 있고,

‘0’ -> 표준입력 : 키보드

‘1’ -> 표준출력 : 모니터

‘2’ -> 표준에러 : 모니터

라는 것이다.

 

즉 fd의 값에 0이 들어가면 키보드로 직접 buf에 쓸 수 있는 것이다.

fd의 값은 atoi( argv[1] ) – 0x1234;이므로, atoi(argv[1])가 0x1234, 즉 4460이면 된다.

그러므로 argv[1]에 4460을 입력하고 “LETMEWIN”을 치면 flag의 내용을 확인할 수 있다.

 

fd@ubuntu:~$ ./fd 4660
LETMEWIN
good job 🙂
mommy! I think I know what a file de@#$!@$@#!@%!@
fd@ubuntu:~$