PWN College CSE 466 - Program Interaction

First Post:

Last Update:

level1

第一关就被卡了好久:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <unistd.h>
void pwncollege(char* argv[],char *env[]){
        char *newenv[]={NULL};
        execve("/challenge/embryoio_level1",newenv,env);
        return ;
}

int main(int argc,char* argv[],char* env[]){
        pid_t fpid;
        fpid=fork();
        if(fpid<0)
                printf("error in fork!\n");
        else if (fpid==0){
                printf("我是子进程\n");
                pwncollege(argv,env);
        }
        else{
                printf("我是父进程\n");
                wait(NULL);
        }
        return 0;
}

但其实不用这么写也可以,只是因为我习惯在 vscode 给的 terminal 里运行程序,所以它会主动去穿一些参数。但如果用 VNC 连的桌面开一个 bash 就可以直接运行程序给的题目二进制了。

level2/3/4

直接运行给个参数就行了。4需要给个环境变量再运行

level5

重定向输入:

1
./embryoio_level5 < /tmp/inujwj

level6

重定向输出:

1
./embryoio_level6 > /tmp/tzdetd

level7

无环境变量去运行该程序。写一个程序调用 execve 去跑目标程序,不过要编译为 bash:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <unistd.h>
void pwncollege(char* argv[],char *env[]){
        char *newenv[]={NULL};
        execve("/challenge/embryoio_level1",newenv,newenv);
        return ;
}

int main(int argc,char* argv[],char* env[]){
        pid_t fpid;
        fpid=fork();
        if(fpid<0)
                printf("error in fork!\n");
        else if (fpid==0){
                printf("我是子进程\n");
                pwncollege(argv,env);
        }
        else{
                printf("我是父进程\n");
                wait(NULL);
        }
        return 0;
}

level8/9/10/11/12/13

写个脚本然后运行程序即可。

level14

脚本里写:

1
env -i /challenge/embryoio_level14

level22

1
2
import subprocess
subprocess.run("/challenge/embryoio_level22")

level23/24/25/26/27

基本不变

level28

1
2
3
#env -i python3 sc.py
import subprocess
subprocess.run(["/challenge/embryoio_level28])

level29

要求用 fork 开子进程然后调用文件,套一下之前的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <unistd.h>

void pwncollege(char* argv[],char *env[]){
        char *newenv1[]={'bash',"/home/hacker/Desktop/sc.sh",NULL};
        char *newenv2[]={NULL};
        execve("/challenge/embryoio_level29",newenv2,newenv2);
        return ;
}

int main(int argc,char* argv[],char* env[]){
        pid_t fpid;
        fpid=fork();
        if(fpid<0)
                printf("error in fork!\n");
        else if (fpid==0){
                printf("我是子进程\n");
                pwncollege(argv,env);
        }
        else{//fpid==1的是父进程
                printf("我是父进程\n");
                wait(NULL);
        }
        return 0;
}

level30/31/32/33/34/35

基本套用给上一个脚本

level36

程序和上一个基本一样,但是把输出用管道符传给 cat:

1
./bash | cat

level37

1
./bash | grep "pwn"

level40

要求重定向 stdin 并通过管道符给程序,并且还要求用 cat。不过 cat 如果有目标文件直接就结束退出了,但是单输入一个 cat 会让程序挂起,然后就可以输入了:

1
cat | ./bash

level42/44

基本同上。

level47

有点麻烦,rev 在无参的情况下看起来和 cat 差不多,但是这次却没成功,于是写了个程序命名为 rev 然后去传参:

1
2
3
4
5
6
7
#include<stdio.h>
#include<stdlib.h>
int main()
{
    printf("%s\n","cfijsyko");
    sleep(5);
}

程序结束后会吐出 flag

level54/56/58

用 python 重复上面的操作

level60/61/65

这次又换会用 fork 去启了,操作不变。

level66

要求用 find 去启动程序:

1
find "/challenge/embryoio_level66" -exec {} \;

level68

要求给很多参数,直接复制粘贴强行突破了。

不过好像有更简单的方式:

1
/challenge/embryoio_level68 `printf ' godxqtxpvg%0.s' {1..284}`

level71

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <unistd.h>
void pwncollege(char* argv[],char *env[]){
        char *newenv1[400]={"bash","sc.sh",NULL};
        char *newenv2[]={"195=zyzycfyyds",0};
        execve("/challenge/embryoio_level71",argv,newenv2);
        return ;
}

int main(int argc,char* argv[],char* env[]){
        pid_t fpid;
        pwncollege(argv,env);
        fpid=fork();
        if(fpid<0)
                printf("error in fork!\n");
        else if (fpid==0){
                printf("我是子进程\n");
                pwncollege(argv,env);
        }
        else{
                printf("我是父进程\n");
                wait(NULL);
        }
        return 0;
}

level72

先进目录,然后用 bash 跑脚本,并重定向即可:

1
/tmp/rdsjif$ bash /home/hacker/Desktop/sc.sh < abjvbe

level73

有点麻烦,最后是这样搞定的:

1
2
#sc.sh
cd /tmp/gngyds;exec /challenge/embryoio_level73
1
2
#sc2.sh
bash sc.sh
1
bash -c "bash sc2.sh"

level74

1
2
3
4
5
import subprocess
ar=["/challenge/embryoio_level74"]
for i in range(200):
    ar.append("xkxnlfngaa")
subprocess.run(ar)

level77

1
2
3
4
5
6
7
8
import subprocess
import os
ar=["/challenge/embryoio_level77"]
for i in range(200):
    ar.append("xhgzegeywm")
os.environ.clear()
os.environ["185"]="pfqthebkev"
subprocess.run(ar)

level79

也是换个目录,不过这次是 python 版本:

1
2
3
4
import subprocess
import os
ar=["/challenge/embryoio_level79"]
subprocess.call(ar,cwd="/tmp/wnufru")

level80

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <unistd.h>
#include<stdlib.h>
void pwncollege(char* argv[],char *env[]){
        char *newenv1[400]={"/challenge/embryoio_level80",NULL};
        for(int i=1;i<100;i++)
        {
                newenv1[i]="oikeqbtrns";
        }
        char *newenv2[]={0};
        execve("/challenge/embryoio_level80",newenv1,newenv2);
        return ;
}
int main(int argc,char* argv[],char* env[]){
        pid_t fpid;
        fpid=fork();
        if(fpid<0)
                printf("error in fork!\n");
        else if (fpid==0){
                printf("我是子进程\n");
                pwncollege(argv,env);
        }
        else{
                printf("我是父进程\n");
                wait(NULL);
        }
        return 0;
}

level83

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <unistd.h>
#include<stdlib.h>
void pwncollege(char* argv[],char *env[]){
        char *newenv1[400]={"/challenge/embryoio_level80",NULL};
        for(int i=1;i<300;i++)
        {
                newenv1[i]="vfnrjapwqf";
        }
        char *newenv2[]={"151=mzjtmpkgda",0};
        execve("/challenge/embryoio_level83",newenv1,newenv2);
        return ;
}
int main(int argc,char* argv[],char* env[]){
        pid_t fpid;
        fpid=fork();
        if(fpid<0)
                printf("error in fork!\n");
        else if (fpid==0){
                printf("我是子进程\n");
                pwncollege(argv,env);
        }
        else{
                printf("我是父进程\n");
                wait(NULL);
        }
        return 0;
}

level85

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <unistd.h>
#include<stdlib.h>
void pwncollege(char* argv[],char *env[]){
        chdir("/tmp/uejsun");
        execve("/challenge/embryoio_level85",argv,env);
        return ;
}



int main(int argc,char* argv[],char* env[]){
        pid_t fpid;
        fpid=fork();
        if(fpid<0)
                printf("error in fork!\n");
        else if (fpid==0){
                printf("我是子进程\n");
                pwncollege(argv,env);
        }
        else{
                printf("我是父进程\n");
                wait(NULL);
        }
        return 0;
}

level86

脚本跑起来之后输入数字即可

level87

不会写脚本,直接手撸了,还好不多

level88/89

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <unistd.h>
#include<stdlib.h>
void pwncollege(char* argv[],char *env[]){
        char *newenv1[400]={"/tmp/rciroo",NULL};
        execve("/challenge/embryoio_level88",newenv1,env);
        return ;
}

int main(int argc,char* argv[],char* env[]){
        pid_t fpid;
        fpid=fork();
        if(fpid<0)
                printf("error in fork!\n");
        else if (fpid==0){
                printf("我是子进程\n");
                pwncollege(argv,env);
        }
        else{
                printf("我是父进程\n");
                wait(NULL);
        }
        return 0;
}

level94

先创建一个 fd=70 的描述符,然后读重定向给 stdin:

1
2
3
4
$cat sc2.sh
wvrrmdmh
$exec 70<sc2.sh
$bash sc.sh 0<&70

level97

1
2
bash sc.sh
kill -SIGUSR2 2346

level99

python 启动后做个计算就行了。

level100

1
2
3
4
5
6
7
8
9
from pwn import *
p=process("/challenge/embryoio_level100")

for i in range(5):
    p.recvuntil("CHALLENGE! Please send the solution for: ")
    data=p.recv()
    p.sendline(str(eval(data)))

p.interactive()

level102

注意,这里的 sleep 是必须的,因为父进程提前结束会让子进程被根进程接管,导致父进程不是 python,过不去题目的检查:

1
2
3
4
5
6
7
8
9
import os
import time
pid = os.fork()
if pid > 0:
    print("父进程,子进程的PID:", pid)
    time.sleep(5)
else:
    print("子进程,父进程的PID:", os.getppid())
    os.execve('/challenge/embryoio_level102', ['jvuwqe'], {})

level103

fifo 管道的使用。

1
2
mkfifo testf
echo ndvbtdxa > testf

另外开个窗口用 python 去跑程序:

1
python3 sc.py < testf

level104/105

104 跟上一题差不多,就是重定向一下输出而已。105 就是把两个都重定向一下

level106

和前面的有点不太一样。先写个 python 去跑程序:

1
2
3
4
5
import subprocess

fd1=open("testf","r")
fd2=open("testf2","w")
p=subprocess.run("/challenge/embryoio_level106",stdin=fd1,stdout=fd2)

然后另外开一个终端:

1
2
cat < testf2 &
cat > testf

这里不能把重定向去掉,比如另外开两个终端分别去 cat 管道文件:

1
2
cat testf2
cat testf

这会导致阻塞。看起来像是文件,但实际使用还是要用重定向的方式去用。

level107

1
2
3
4
5
6
7
import subprocess
import os
import time
from pwn import *
context.log_level="debug"
fd=os.dup2(102,102)
p=subprocess.run("/challenge/embryoio_level107",stdin=102,pass_fds=[0,1,2,102])

level110

正常启动,然后另外调用 kill 杀掉就行了。

level112/113/115/117/118

正常启动就行了,基本上跟之前的操作一样,不过 113 几个算术题另外拿 python 算了一下。

level120

换个新方法:

1
2
3
4
5
void pwncollege(char* argv[],char *env[]){
        dup2(0,103);
        execve("/challenge/embryoio_level120",argv,env);
        return ;
}

level123

跟之前差不多。

level126

要求是脚本执行,但是不会写 bash 所以用通道的方法转给 python 去解决。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
f1=open("./testf","rb")
f2=open("./testf2","wb")
sum=0
for i in range(6):
    f1.readline()

for i in range(3000):
    s=f1.readline()
    if sum >=500:
        print(s)
        print(f1.read())
        break
    index=s.find(b": ")
    if index != -1:
        sum+=1
        t1=s[index+2:-1]
        t2=eval(t1)
        print("%d : %d"%(sum,t2))
        f2.write(b"%d\n"%t2)
        f2.flush()

level128

500 个信号,偷个懒,把列表抄过来直接跑:

1
2
3
4
5
6
import os
import subprocess
sig=['SIGABRT', 'SIGUSR1', 'SIGUSR1', 'SIGUSR2', 'SIGABRT',
for i in sig:
    code="kill "+"-"+i[3:]+" 5590"
    subprocess.run(code,shell=True)

不过不知道为什么这道题没办法用上一题的 fifo 文件去传输出,有点奇怪

level131

1
2
3
4
5
6
7
from pwn import *

p=process("/challenge/embryoio_level131")
for i in range(500):
    p.recvuntil("Please send the solution for: ")
    p.sendline(str(eval(p.recv())))
p.interactive()

level133

照搬上面

level136

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fd1=open("testf","r")
fd2=open("testf2","w")
for i in range(6):
    fd1.readline()
sum =1

for i in range(3000):
    line=fd1.readline()
    if sum>500:
        print(line)
        for i in range(5):
            print(fd1.readline())
        break
    if "Please send the solution for: " in line:
        temp=line.split(": ")[1]
        res=eval(temp)
        fd2.write(str(res)+"\n")
        fd2.flush()
        print(str(sum)+":"+str(res))
        sum+=1
    else:
        print(line)

level138

套脚本

level140

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define SERVER_IP "0.0.0.0"
#define SERVER_PORT 1210
#define BUFFER_SIZE 1024
int main() {
int sockfd;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE];
char ans[BUFFER_SIZE];
// 创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}

// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
server_addr.sin_port = htons(SERVER_PORT);

// 连接到服务器
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}

while(1)
{
memset(buffer, 0, BUFFER_SIZE);
if (recv(sockfd, buffer, BUFFER_SIZE, 0) == -1) {
perror("recv");
exit(EXIT_FAILURE);
}
if(strlen(buffer)>0)
{
printf("Received: %s\n", buffer);
if(!memcmp("[TEST] CHALLENGE! Please send the solution",buffer,strlen(("[TEST] CHALLENGE! Please send the solution"))))
{

memset(ans, 0, BUFFER_SIZE);
read(0,ans,BUFFER_SIZE);
if (send(sockfd, ans, strlen(ans), 0) == -1) {
perror("send");
exit(EXIT_FAILURE);
}
}

}
}
close(sockfd);
return 0;
}

level141

手撸:

1
2
3
from pwn import *
p=remote("0.0.0.0",1321)
p.interactive()

level142

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#define SERVER_IP "0.0.0.0"
#define SERVER_PORT 1719
#define BUFFER_SIZE 1024
int pwncollege();
int main()
{
pwncollege();
}

int pwncollege() {
int sockfd;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE];
char ans[BUFFER_SIZE];
// 创建套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}

// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
server_addr.sin_port = htons(SERVER_PORT);

// 连接到服务器
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}

while(1)
{
memset(buffer, 0, BUFFER_SIZE);
if (recv(sockfd, buffer, BUFFER_SIZE, 0) == -1) {
perror("recv");
exit(EXIT_FAILURE);
}
if(strlen(buffer)>0)
{
printf("Received: %s\n", buffer);
if(!memcmp("[TEST] CHALLENGE! Please send the solution",buffer,strlen(("[TEST] CHALLENGE! Please send the solution"))))
{

memset(ans, 0, BUFFER_SIZE);
read(0,ans,BUFFER_SIZE);
if (send(sockfd, ans, strlen(ans), 0) == -1) {
perror("send");
exit(EXIT_FAILURE);
}
}

}
}
close(sockfd);
return 0;
}