Program Interaction

starlitxiling Lv3

1

1
/bin/bash

2

1
2
/bin/bash
/challenge/embryoio_level2

然后输入它提供的值就好了
or

1
2
bash
/challenge/embryoio_level2 <<< pkovncmc

3

1
2
/bin/bash
/challenge/embryoio_level3 -(arguments)

4

1
2
3
/bin/bash
export KEY="VALUE" #这里要加引号,不然会报错
/challenge/embryoio_level4

or

1
2
/bin/bash
env KEY=VALUE /challenge/embryoio_level4

5

1
2
3
4
5
/bin/bash
cd /tmp
mkdir /etgyzz
vim etgyzz (写入fzgfqswr)
/challenge/embryoio_level5 < /tmp/etgyzz

6

1
2
/bin/bash
/challenge/embryoio_level6 > /tmp/vrpfrz

然后再从/tmp/vrpfrz文件中复制flag就好了

7

1
2
/bin/bash
env -i /challenge/embryoio_level7 #表示以空环境运行后面的命令

8

1
2
3
4
5
6
vim my_script.sh
#!/bin/bash

/challenge/embryoio_level8

bash my_script.sh

9

1
2
3
4
5
6
7
8
9
 vim my_script.sh
#!/bin/bash

/challenge/embryoio_level9

bash my_script.sh

kdubhqar

10

1
2
3
4
5
6
vim my_script.sh
#!/bin/bash

/challenge/embryoio_level10 bojahpqwxu

bash my_script.sh

这里最开始一直在想怎么传KEY:VALUE这类型的参数,后面又重新看了n遍题目反应过来是要argv[num]=value,然后想到第三题直接/challenge/embryoio_level3 arguments,于是修改my_script.sh中的命令就好了
(这里能这么传是因为num=1,详见68)

11

1
2
3
4
5
6
7
8
export anfzwf=vzsqapifsw

vim my_script.sh
#!/bin/bash

/challenge/embryoio_level11

bash my_script.sh

or

1
2
3
4
5
6
7
vim my_script
#!/bin/bash

/challenge/embryoio_level11


env anfzwf=vzsqapifsw bash my_script.sh

12

1
2
3
4
5
6
7
8
9
vim /tmp/yujbjc
uphcfwxv

vim my_script.sh
#!/bin/bash

/challenge/embryoio_level12

bash my_script.sh < /tmp/yujbjc

13

1
2
3
4
5
6
7
8
vim my_script.sh
#!/bin/bash

/challenge/embryoio_level13

bash my_script.sh < /tmp/smtqwm
cat /tmp/smtqwm

14

1
2
3
4
5
6
vim my_script.sh
#!/bin/bash

env -i /challenge/embryoio_level14

bash my_script.sh

22

1
vim interaction_python.py
1
2
3
import subprocess
subprocess.run(["/challenge/embryoio_level22"])

1
2
python interaction_python.py

这里最开始用的是subprocess.call,但是会报错为是运行在dash环境下而不是python环境,后经查阅尝试使用run通过了

subprocess lib
call函数在python3.5版本之后在大多数情况下已经被run函数替代,需要捕捉标准输出和标准错误的时候也应当使用run代替

23

1
vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level23"])
1
2
python interaction_python.py
ulelosql

24

1
vim interaction_python.py
1
import subprocess.run(["/challenge/embryoio_level24","ebyhyvaqeu"])
1
python interaction_python.py

25

1
2
export hapuuh=zuwaknffap
vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level25"])
1
python interaction_python.py

or

1
vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level25"])
1
env hapuuh=zuwaknffap python interaction_python.py

26

1
2
3
4
vim /tmp/bpamfl
albupjkk

vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level26"])
1
python interaction_python.py < /tmp/bpamfl

or

1
2
3
vim /tmp/bpamfl
albupjkk
vim interaction_python.py
1
2
3
4
5
6
from pwn import *
import os
password_file_fd = os.open("/tmp/bpamfl",os.O_RDWR)
print(f"Opening password file on FD:{password_file_fd}")
p = process("/challenge/embryoio_level26",stdin=password_file_fd)
p.interaction()
1
python interaction_python.py

27

1
2

vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level27"])
1
2
3
python interaction_python.py > /tmp/dkyeje

cat /tmp/dkyeje

28

1
vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level28"])
1
2
env -i python interaction_python.py

29

1
vim interaction_c.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level29",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

if(WIFEXITED(status)){
int exit_status = WEXITSTATUS(status);
printf("child process exited with exit status:%d\n",exit_status);
}else if(WIFSIGNALED(status)){
int terminate_signal = WTERMSIG(status);
printf("child process exited with termination signal:%d\n",terminate_signal);
}
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
gcc -o interaction_c interaction_c.c
./interaction_c

这里要注意waitpid的调用,如果不加waitpid,则有可能父进程在子进程执行之前终止(可能导致子进程成为一个孤儿进程),也有可能子进程在父进程之前执行完毕(可能导致子进程成为一个僵尸进程)错误示例可看80

30

1
vim interaction_c.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level29",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
3
4
gcc -o interaction_c interaction_c.c
./interaction_c

wwrqjqbv

31

1
vim interaction_c.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level31","jbxnucvjoe",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
3
4
gcc -o interaction_c interaction_c.c
./interaction_c


32

1
vim interaction_c.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level32",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
3
gcc -o interaction_c interaction_c.c
env swzqlt=prjzxvuzmr ./interaction_c

or

1
2
export swzqlt=prjzxvuzmr
./interaction

33

1
2
3
4
vim /tmp/hdkihv
wknjywzj

vim interaction.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level33",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
gcc -o interaction_c interaction_c.c
./interaction_c < /tmp/hdkihv

or

1
2
3
4
vim /tmp/hdkihv
wknjywzj

vim input_challenge.c
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
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int pwncollege() {

FILE *file = fopen("/tmp/hdkihv","r");
if (file == NULL) {
perror("Failed to open input file");
exit(1);
}

pid_t pid = fork();
if (pid < 0) {
perror("Failed to fork");
exit(1);
} else if (pid == 0) {
dup2(fileno(file), STDIN_FILENO);
fclose(file);

execl("/challenge/embryoio_level33",NULL);
perror("Failed to execute command");
exit(1);
} else {
wait(NULL);
}

return 0;
}
int main()
{
pwncollege();
return 0;
}
1
2
gcc -o input_challenge input_challenge.c
./input_challenge

请注意这里上面使用的是execv函数,下面使用的是execl函数,这两个函数的区别在于参数的传递方式。

conclusion

execl:接受可变数量的参数来指定要执行的程序以及传递给该程序的命令行参数,以NULL结束。

execv:接受一个指向参数字符串数组的指针,数组中的每个字符串都是要传递给新程序的命令行参数,以NULL结束。

34

1
vim interaction.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level34",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
3
gcc -o interaction_c interaction.c
./interaction_c > /tmp/ivyyzs
cat /tmp/ivyyzs

or

1
vim output_challenge.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <fcntl.h>
#include <unistd.h>

int pwncollege()
{
int outputFile = open("/tmp/ivyyzs",O_WRONLY | O_CREAT | O_TRUNC,0644);
if(outputFile == -1){
perror("open");
return 1;
}
if(dup2(outputFile,STDOUT_FILENO) == -1){
perror("dup2");
return 1;
}
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level34",NULL};
execv(args[0],args);
perror("execv");
exit(1);
}else{
int status;
waitpid(pid,&status,0);
exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
3
4
gcc -o output_challenge output_challenge.c
./output_challenge
cat /tmp/ivyyzs

35

1
vim interaction.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level34",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
gcc -o interaction_c interaction_c.c
env -i ./interaction_c

36

1
2
/bin/bash
/challenge/embryoio_level36 | cat

这里一开始被/dev/stdout误导了,一直写的是cat /dev/stdout,后面才反应过来/challenge/embryoio_level的输出就是stdout

37

1
2
/bin/bash
/challenge/embryoio_level37 | grep pwn

40

1
2
3
/bin/bash
cat | /challenge/embryoio_level40
doqaxpmr

42

1
2
3
4
5
6
vim my_script.sh
#!/bin/bash
/challenge/embryoio_level42

bash my_script.sh | cat

44

1
2
3
4
5
6
vim my_script.sh
#!/bin/bash
/challenge/embryoio_level44

bash my_script.sh | sed -n '1,20p'

47

1
2
3
4
5
6
vim my_script.sh
#!/bin/bash
rev | /challenge/embryoio_level47

bash my_script.sh
hlwhngrm(给的是mrgnhwlh)

or

1
2
3
4
5
6
vim my_script.sh
#!/bin/bash
/challenge/embryoio_level47

rev | rev | bash my_script.sh
mrgnhwlh(ctrl+D)-

rev命令放到sh里面的时候,注意密码要颠倒一下(因为使用了rev),然后输入完之后要用ctrl+D,而不是Enter

记录一下相关的两道题,但40可以使用Enter

54

1
vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level54"])
1
2
python interaction_python.py | cat

or

1
vim interaction_python.py
1
2
3
4
5
from pwn import *
import os
p_cat = process("cat")
p = process("/challenge/embryoio_level54",stdout=p_cat.stdin)
p_cat.interactive()
1
python interaction_python.py

56

1
vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level56"])
1
python interaction_python.py | sed -n "1,50p"

58

1
vim interaction_python.py
1
2
import subprocess
subprocess.run(["/challenge/embryoio_level58"])
1
2
cat | python interaction_python.py
zyfswacr

60

1
vim interaction.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level60",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
3
gcc -o interaction_c interaction.c
./interaction_c | cat

61

1
vim interaction.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level60",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
3
gcc -o interaction_c interaction.c
./interaction_c | grep pwn

65

1
vim interaction.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
pid_t pid;
pid = fork();

if(pid < 0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level65",NULL};
execv(args[0],args);

exit(1);
}else{
int status;
waitpid(pid,&status,0);

exit(1);
}
return 0;
}

int main(int argc,char **argv)
{
pwncollege();
return 0;
}
1
2
3
4
gcc -o interaction_c interaction.c
rev | rev | ./interaction_c
bffjthhw

66

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

请注意}\有空格,没有空格的话会报错find: missing argument to ``exec这个错误

68

1
2
3
4
5
6
7
vim my_script.sh
#!/bin/bash

/challenge/embryoio_level68 $(seq 1 130) \ nfotwcprbp

bash my_script.sh

71

1
2
3
4
5
6
vim my_script.sh
#!/bin/bash

env -i env 196=ueaivmvvui /challenge/embryoio_level71 $(seq 1 302) cptxifnelk

bash my_script.sh

72

1
2
3
4
5
6
7
8
9
10
mkdir /tmp/ruykru
touch /tmp/ruykru/yyajda

vim my_script.sh
#!/bin/bash

cd /tmp/ruykru && /challenge/embryoio_level72 < yyajda

bash my_script.sh

这里最开始使用的是|符号,后面查阅资料后换成&&

区别:
|:管道操作符,从一个命令的输出将数据传递给另一个命令进行处理
&&:逻辑与操作符,在前一个命令成功执行后(返回退出码为0),才继续执行下一个命令

73

1
vim demo.c
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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int args,char *argv[],char *env[])
{
pid_t pid;
pid = fork();

if(pid<0){
exit(1);
}else if(pid == 0){
char *args[] = {"/challenge/embryoio_level73",NULL};
chdir("/tmp/uzjwek");
//execv(args[0],args);
execve(args[0],argv,env);
printf("I am a child process");
exit(1);
}else{
int status;
waitpid(pid,&status,0);
exit(1);
}
return 0;
}
1
2
3
gcc demo.c -o bash
./bash

震惊我一整年的题!!!(纯属自己蠢逼一个)
先看题目要求:

这里的要求是shell脚本、工作目录在/tmp/uzjwek,然后祖父进程和运行挑战所在的进程目录要不一样。一开始是想在shell脚本中运行使用()创建子进程,然后切换目录运行什么的,但是一直不能拿到flag。后面查了一些东西后再查看了checker.py后:

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
def check_bash(process):
print("[TEST] Checking to make sure the process is the bash shell. If this is a check for the parent process, then,")
print("[TEST] most likely, this is what you do by default anyways, but we'll check just in case...")
check_exe_basename(process, 'bash')
assert len(process.cmdline()) == 1, f"The shell process must be running in its default, interactive mode (/bin/bash with no commandline arguments). Your commandline arguments are: {process.cmdline()}"

def check_shellscript(process):
print("[TEST] Checking to make sure the process is a non-interactive shell script.")

assert os.path.basename(process.exe()) in [ 'sh', 'bash' ], f"Process interpreter must be 'sh' or 'bash'. Yours is: {os.path.basename(process.exe())}"
assert len(process.cmdline()) == 2 and process.cmdline()[1].endswith(".sh"), f"The shell process must be executing a shell script that you wrote like this: `bash my_script.sh`"

PROCESS_TYPE_CHECKERS = {
'python': check_python,
'bash': check_bash,
'shellscript': check_shellscript,
'ipython': check_ipython,
'binary': check_binary,
'netcat': lambda p: check_exe_basename(p, 'nc'),
'socat': lambda p: check_exe_basename(p, 'socat'),
'echo': lambda p: check_exe_basename(p, 'echo'),
'cat': lambda p: check_exe_basename(p, 'cat'),
'grep': lambda p: check_exe_basename(p, 'grep'),
'sed': lambda p: check_exe_basename(p, 'sed'),
'find': lambda p: check_exe_basename(p, 'find'),
'rev': lambda p: check_exe_basename(p, 'rev'),
}

这一段的判断是有点草率的,它只是检测运行的程序名为bash即可,所以后面实在没办法用C完成了整个程序,这样就能正常的在进程中切换目录然后运行程序使祖父程序和挑战程序的目录不一样,就可以通过测试拿到flag了。使用env参数是为了传递环境变量给execve函数通过检测。

在经过请教discordTipsy大佬后,得到了符合题目要求的解法。记录如下:

1
2
3
4
5
vim my_script.sh
#!/bin/bash
bash -c "cd /tmp/uzjwek && /challenge/embryoio_level73"

bash my_script.sh


使用 -c 选项可以将一整个命令字符串作为参数传递给 bash,而没有使用 -c 选项则将命令作为独立的参数传递给 bash
简单来说就是有-c的时候表示两条命令作为一个整体被传递给bash执行,&&是一个控制流操作符,表示在执行前一个命令成功后才执行后一个命令,所以总的来说是在/tmp/usjwek目录下执行/challenge/embryoio_level73
而无-c参数则就是两个单独的命令,彼此之间并无相互影响,所以bash "cd /tmp/uzjwek && /challenge/embryoio_level73"自然无法成功

:这里或许还可以参考8889这两道题

74

1
vim interaction_python.py
1
2
3
4
import subprocess
args = ["/challenge/embryoio_level74"] + [""]*28 + ["sjzzclepas"]
subprocess.run(args)

1
python interaction.py

77

1
vim interaction_python.py
1
2
3
import subprocess  
args = ["/challenge/embryoio_level77"] + [""]*100 + ["mivegfmnto"]
subprocess.run(args)
1
2
env -i env 262=obtersrpps python interaction_python.py

79

1
vim interaction_python.py
1
2
import subprocess	   subprocess.run(["/challenge/embryoio_level79"],cwd="/tmp/trlvty")

1
python interaction_python.py

80

1
vim pg_inac80.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
void pwncollege() {
    pid_t pid;
    char *args[328];
    args[0] = "/challenge/embryoio_level80";
    for(int i=1;i < 328;i++){
        args[i] = "wesyhjkrni";
    //args[i] = "a";(改循环之后使用这行也可以完成此题)
    }
    // args[327] = "wesyhjkrni";
    args[328] = NULL;
    pid = fork();
    if(pid == 0){
        printf("child process is created\n");
        printf("args[0] = %s\n",args[0]);
        printf("args[327] = %s\n",args[327]);
        execv(args[0],args);
        printf("program finished\n");
    }else if(pid > 0){
        wait(1);
    }else{
        int status;
        waitpid(pid,&status,0);
        printf("failed to create child process.\n");
        wait(1);
    }
}
int main(int argc,char **argv) {
    pwncollege();
    return 0;
}
1
2
gcc -o pg_inac80 pg_inac80.c
./pg_inac80

这题前前后后估计写了5个小时了(也是道自己蠢逼题)
先看题目要求:

要求其实很简单,就是二进制文件运行加个参数。
主要就是卡在这个参数,一开始是想在C中有没有什么方法能够指定数组的某个位置写进参数,最后试了半天发现这样做出错,因为0和指定位置之间没有值导致指定位置的值会被作为第一个参数传进去,所以也就不符合要求了。
后面就是标准的指定数组大小,使用循环初始化数组,但是这里最开始我使用的是NULL去初始化之间的值,但是经过gdb等调试后和查阅资料后发现execv这类函数是在遇到NULL之后就会停止执行了(这也是为什么前面的args最后都要加NULL的原因)。然后后面使用过0 1这种数字也不行,排查后才反应过来我的是字符数组,当然不能使用数字,改成字符之后就通过了。这里还要注意waitpid的使用,不然有时候会有输出有时候没输出,waitpid具体见29

conclusion

从这道题目可以看出execv这类函数的参数位置计算,args[327]就是execv执行程序时候的第327个参数,也就是说被执行程序本身是作为第0个参数传入的而不是第1个(应该可以这么理解?),还有就是记得execv是执行到NULL就会自动停止。

83

1
vim interaction_c.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
int pwncollege()
{
        pid_t pid;
        pid = fork();
        if(pid < 0){
                exit(1);
        }else if(pid == 0){
                char *args[329];
                args[0] = "/challenge/embryoio_level83";
                for (int i = 1; i < 130; i++) {
                        args[i] = "a";}
                args[130] = "tvutqvsrlj";
                args[131] = NULL;
                execv(args[0],args);
                exit(1);
        }else{
                int status;
                waitpid(pid,&status,0);
                exit(1);
        }
        return 0;
}
int main(int argc,char **argv)
{
        pwncollege();
        return 0;
}
1
2
gcc -o interaction_c interaction_c.c
env -i env 336=whxtxwutel ./interaction_c

85

1
vim interaction_c.c
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
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int pwncollege()
{
        pid_t pid;
        pid = fork();
        if(pid<0){
                exit(1);
        }else if(pid == 0){
                char *args[] = {"/challenge/embryoio_level85",NULL};
                chdir("/tmp/ykjdxt");
                execv(args[0],args);
                printf("I am a child process");
                exit(1);
        }else{
                int status;
                waitpid(pid,&status,0);
                exit(1);
        }
        return 0;
}
int main(int argc,char **argv)
{
        pwncollege();
        return 0;
}
1
2
gcc -o interaction_c interaction_c.c
./interaction_c

类同73,只不过这次是可以正当使用了
notice:这道题和73题写法不一样,细节上也不一样,可以对比一下

86

一开始是直接输入答案的,但是写到87题的时候感觉出题人的本意不是这样的,于是写了蛮久的87题写出来了,详细记录在87题,以下只贴出本题的答案

1
2
3
4
vim my_script.sh
/challenge/embryoio_level86

vim 86.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *

p = process(["bash","my_script.sh"])

for i in range(1):
output = p.recvuntil(b"CHALLENGE! Please send the solution for:")
print(output.decode("utf-8"))
number = p.recvuntil(b"\n").strip()
print(number.decode("utf-8"))

result = eval(number)
print(result)
p.sendline(str(result))
print(p.recvuntil("CORRECT!").decode("utf-8"))


print(p.recvall(timeout=1).decode("utf-8"))
1
python3 86.py

87

先贴解题记录

1
2
3
vim my_script.sh
/challenge/embryoio_level87
vim 87.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
p = process(["bash","my_script.sh"])
for i in range(5):
    output = p.recvuntil(b"CHALLENGE! Please send the solution for: ")
    # output = p.recvuntil(b'CHALLENGE! Please send the solution for: ')
    # print(output.decode("utf-8"))
    number = p.recvuntil(b"\n").strip()
    # print(number.decode("utf-8"))
    result = eval(number)
    # print(result)
    p.sendline(str(result))
print(p.recvuntil("CORRECT!").decode("utf-8"))


print(p.recvall(timeout=1).decode("utf-8"))
1
python3 87.py

写到这道题目最开始惯性思维是按照题目要求用bash脚本解决,所写的bash脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
output=$(/challenge/embryoio_level87)
problem=$(echo "$output" | grep "CHALLENGE!" | awk -F": " '{print $2}')

count=0

while [$count -lt 5];do
if[ -z "$problem" ];then
break;
fi

echo "Solving problem $((count+1)): $problem..."
result=$(echo "$problem" | bc)
echo "Result: $result"

output=$(/challenge/embryoio_level87 <<< "$result")
problem=$(echo "$output" | grep "CHALLENGE!" | awk -F": " '{print $2}')

((count++))
done

flag=$(echo "output" | grep "pwn.college")
echo "Flag: $flag"
  • awk -F": " '{print $2}':使用 awk 工具来处理文本。参数 -F": " 表示以冒号和空格作为字段分隔符,这样会将每行分割成多个字段。$2 表示打印第二个字段,也就是在冒号和空格后面的内容,即挑战的具体数学问题。
  • 但是这个脚本并不能正确运行,它在运行之后都需要按下回车才能继续运行,这样会导致发送回去的result产生错位(到现在也没明白)
  • 后面询问了Tipsy佬后知道佬是使用python脚本来运行my_script.sh来完成本题的,所以我尝试按照这个思路解决本题
  • 按照下面这个视频提供的思路,完成了python脚本的编写。遇到的问题有:
  1. 没有办法从一大段字符串中提取到需要的算术式,后面是使用number = p.recvuntil(b"\n").strip()解决的。这里需要注意的是p.recvuntil()是一个阻塞操作,它会等待直到找到匹配的字符串才会继续执行。所以这里number只能获取output之后的输出知道\n换行符。
  2. p.sendline()最开始是直接将result传了进去,后面调试后发现p.sendline()需要的是字符串,所以str(result)解决了。
  3. p.recvall(timeout=1): 从连接 p 中接收所有的数据,直到连接关闭或超时。参数 timeout=1 表示最多等待 1 秒钟。这样就可以看到所有的输出了。
    本脚本相关视频

88

1
2
3
4
5
ln -s /challenge/embryoio_level88 /tmp/lnumjg

export PATH=.:$PATH
echo "/tmp/lnumjg" > my_script.sh
bash my_script.sh

其实这里只需要知道一个点就是程序运行的argv[0]这个参数是程序本身所在的路径,而且是绝对路径,以上的操作就可以理解了。题目所给的提示在89

89

这是题目的hints:

翻译一下就是:
argv[0]从要执行的程序路径分别传递到execve()系统调用中。这意味着它不必与程序路径相同,您可以实际控制它。这对于不同的执行方法是不同的。例如,在C中,您只需要传入不同的argv[0]Bash有几种方法可以做到这一点,但其中一种方法是使用符号链接(例如,ln -s命令)和PATH环境变量的组合。

1
2
3
4
5
6
7
ln -s /challenge/embryoio_level89 cmwgvr


#将当前目录作为首个PATH变量
export PATH=.:$PATH
echo "cmwgvr" > my_script.sh
bash my_script.sh

94

1
2
3
4
5
6
7
8
9
vim my_script.sh
#!/bin/bash
echo "adbsmqfp" > /tmp/demo
exec 82< /tmp/demo
# exec 82< <(echo "YourStringHere")
/challenge/embryoio_level94 <&82

bash my_script.sh

这里exec是将/tmp/demo中的内容关联到文件描述符82,这里只能使用文件的形式,不能exec 82< adbsmqfp这样。

97

1
2
3
4
5
6
7
vim my_script.sh
#!/bin/bash
/challenge/embryoio_level97

bash my_script.sh
kill -SIGABRT 1081

这里其实就是要求在程序运行的时候向指定的进程号发送信号,使用kill命令就好了。

99

1
vim interaction_python.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
# p = subprocess.run(["/challenge/embryoio_level99"])
p = process(["/challenge/embryoio_level99"])
for i in range(1):
    output = p.recvuntil(b"CHALLENGE! Please send the solution for: ")
    print(output.decode("utf-8"))
    number = p.recvuntil(b"\n").strip()
    print(number.decode("utf-8"))
    result = eval(number)
    p.sendline(str(result))
print(p.recvuntil(b"CORRECT!".decode("utf-8")))


print(p.recvall(timeout=1).decode("utf-8"))
1
python3 interaction_python.py

这里和89里面差不多就好了,就是要注意我一开始使用的是subprocess,但是这里面并没有recvuntil()这一类的方法,所以后面使用的是process(),但感觉理论上使用subprocess里面的pOpen()这种也能通过,只是感觉过程比较繁琐,所以没有尝试,可能后面有时间会来补一下。

100

1
vim interaction_python.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
# p = subprocess.run(["/challenge/embryoio_level99"])
p = process(["/challenge/embryoio_level100"])
for i in range(5):
    output = p.recvuntil(b"CHALLENGE! Please send the solution for: ")
    print(output.decode("utf-8"))
    number = p.recvuntil(b"\n").strip()
    print(number.decode("utf-8"))
    result = eval(number)
    p.sendline(str(result))
print(p.recvuntil(b"CORRECT!".decode("utf-8")))


print(p.recvall(timeout=1).decode("utf-8"))
1
python3 interaction_python.py

102

89一样的套路

1
2
3
4
ln -s /challenge/embryoio_level102 rtszrh
export PATH=.:$PATH

vim 102.py
1
2
3
4
5
6
7
from pwn import *

# subprocess.run(["rtszrh"])

p = process(["rtszrh"])
print(p.recvall(timeout=1).decode("utf-8"))

1
2
python3 102.py

103

先看题目要求:

解释一下就是其实还是和以前的差不多,就是要使用fifo这个特殊的文件,它的本质就是管道,使用man page可以查看fifo,然后在mkfifo in后再在代码中使用dup2函数重定向一下输入,再将hardcoded password输入到in中就好了

1
2
mkfifo in
vim 103.py
1
2
3
4
5
6
7
from pwn import *

pipe_fd = os.open("/home/hacker/in", os.O_RDWR)

os.dup2(pipe_fd, 0)

subprocess.run(["/challenge/embryoio_level103"])
1
2
python3 103.py
echo dhfxmaac > in

104


这里和上面差不多,只要知道0是标准输入,1是标准输出,2是标准错误输出就好了。就是因为这里你重定向标准输出到了fifo中,所以你要事先在另一个终端中cat out去等待输出,然后执行了需要实现的程序后才能看到输出

1
2
mkfifo out
vim 104.py
1
2
3
4
from pwn import *
pipe_fd = os.open("/home/hacker/out",os.O_RDWR)
os.dup2(pipd_fd,1)
subprocess.run(["/challenge/embryoio_level104"])
1
2
cat out
python3 104.py

105

1
2
3
mkfifo in
mkfifo out
vim 105.py
1
2
3
4
5
6
from pwn import *
pipe_in = os.open("/home/hacker/in",os.O_RDWR)
pipe_out = os.open("/home/hacker/out",os.O_RDWR)
os.dup2(pipe_in,0)
os.dup2(pipe_out,1)
subprocess.run(["/challenge/embryoio_level105"])
1
2
3
cat out
python3 105.py
echo wseecbpr > in
  • O_RDONLY:以只读方式打开文件。
  • O_WRONLY:以只写方式打开文件。
  • O_RDWR:以读写方式打开文件。
    以上标志其实是C语言的系统调用open中使用的选项,用于控制文件的打开模式。

106

1
vim 106.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *

pipe_in = os.open("/home/hacker/in",os.O_RDWR)
pipe_out = os.open("/home/hacker/out",os.O_RDWR)
p = process(["/challenge/embryoio_level106"],stdout=os.dup2(pipe_out,1),stdin=os.dup2(pipe_in,0))
for i in range(1):
    output = os.read(pipe_out, 4096)
    start_idx = output.find("CHALLENGE! Please send the solution for: ") + len("CHALLENGE! Please send the solution for: ")
    end_idx = output.find("\n", start_idx)
    number = output[start_idx:end_idx].strip()
    print(output)
    number = re.search(r"CHALLENGE! Please send the solution for: (.+)\n", output)
    print(number)
    result = eval(number)
    os.write(pipe_in,result)
1
2
3
python3 106.py
cat out
echo result > in

上面是自己结合前面的题自己写的,但是写完之后感觉是有点蠢的,尤其是提取算术式那部分,感觉还是要使用recvuntil()这个方法更好。这里并不能像前面那样直接使用p.recvuntil()这种方法,因为我们是使用了fifo管道来进行输入输出。后经询问后Tipsy佬后得到了下面这种解决方法:
讲解视频

1
vim 106.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *

pipein_read = os.open("in",os.O_RDWR)
pipein_write = os.open("in",os.O_WRONLY)
pipeout_read = os.open("out",os.O_RDWR)
pipeout_write = os.open("out",os.O_WRONLY)

p_in = process("cat",stdout=pipein_write)
p = process("/challenge/embryoio_level106",stdin=pipein_read,stdout=pipeout_write)
p_out = process("cat",stdin=pipeout_read)
p_out.recvuntil(b"solution for: ")
number=p_out.recvuntil(b"\n")
p_in.sendline(number)
p_out.interactive()

107

1
vim 107.py
1
2
3
4
from pwn import *
os.dup2(0,324)
p = process("/challenge/embryoio_level107",close_fds=False)
print(p.recvall(timeout=2).decode("utf-8"))
1
python3 107.py <<< dpfuhyem


这个参数就是关闭这个关掉其他文件描述符的参数。

110

1
vim 110.py
1
2
3
4
from pwn import *
subprocess.run(["/challenge/embryoio_level110"])
# p = process("/challenge/embryoio_level110")
# p.interactive()
1
2
python3 110.py
kill -SIGHUP PID

112

详见136

113

详见136

115

1
vim 115.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int pwncollege()
{
    return 0;
}

int main(int args,char *argv[],char *env[])
{
    pwncollege();
    pid_t pid;
    pid = fork();

    if(pid < 0){
        exit(1);
    }else if(pid == 0){
        // char *args[] = {"tajrwe", "/challenge/embryoio_level115", NULL};
        // execv(args[1], args);
        char *args[] = {"tajrwe", NULL};
        execv("/challenge/embryoio_level115", args);
        // char *args[] = {"tajrwe",NULL};
        // execvp("/challenge/embryoio_level115",args);
        exit(1);
    }else{
        int status;
        waitpid(pid,&status,0);
        exit(1);
    }
    return 0;
}
1
2
gcc -o 115 115.c
./115

这里不需要和上面一样ln -s这样88,在C中可以直接指定argv[0]的值,本题还尝试分别使用了execvexecvp两个函数

116

1
2
mkfifo in
vim 116.c
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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

void pwncollege(){}

int main(int *agrc,char *argv[]){
    int pid = fork();
    if(pid == 0){
        char *argv[] = { NULL};
        char *envp[] = { NULL};
        int pipe_in = open("/home/hacker/in",O_RDWR);
        dup2(pipe_out,STDIN_FILENO);
        execve("/challenge/embryoio_level116",argv,envp);
  //execv("/challenge/embryoio_level116",NULL);
    }else{
        waitpid(pid,NULL,0);
    }
    return 0;
}

1
2
3
gcc -o 116 116.c
./116
echo "qhrysiws" > in

学会使用dup2函数就行了

117

1
2
mkfifo out
vim 117.c
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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

void pwncollege(){}

int main(int *agrc,char *argv[]){
    int pid = fork();
    if(pid == 0){
        char *argv[] = { NULL};
        char *envp[] = { NULL};
        int pipe_out = open("/home/hacker/out",O_RDWR);
        dup2(pipe_out,STDOUT_FILENO);
        execve("/challenge/embryoio_level117",argv,envp);
        //execv("/challenge/embryoio_level117",NULL);
    }else{
        waitpid(pid,NULL,0);
    }
    return 0;
}

1
2
3
gcc -o 117 117.c
./117
cat out

118

1
vim 118.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

void pwncollege(){}

int main(int *argc, char *argv[]){
    int pid = fork();
    if(pid == 0){
        int pipe_in = open("/home/hacker/in",O_RDWR);
        int pipe_out = open("/home/hacker/out",O_RDWR);
        dup2(pipe_in,STDIN_FILENO);
        dup2(pipe_out,STDOUT_FILENO);
      execv("/challenge/embryoio_level118",NULL);
    }else{
        waitpid(pid,NULL,0);
    }
    return 0;
}
1
2
3
gcc -o 118 118.c
cat out
echo "cpkzuebb" > in

120

1
2
mkfifo in
vim 120.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

void pwncollege(){}

int main(int *argc,char *argv[]){
    int pid = fork();
    if(pid == 0){
        int pipe_in = open("/home/hacker/in",O_RDWR);
        char *argv[] = {"/challenge/embryoio_level120",NULL};
        dup2(pipe_in,56);
        execv(argv[0],argv);
    }else{
        waitpid(pid,NULL,0);
    }
    return 0;
}
1
2
gcc -o  120 120.c
echo "ozsyamkq" > in

123

1
vim 123.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void pwncollege(){}
int main(int *argc,char *argv[]){
    int pid = fork();
    if(pid == 0){
        char *argv[] = {"/challenge/embryoio_level123",NULL};
        execv(argv[0],argv);
    }else{
        waitpid(pid,NULL,0);
    }
    return 0;
}
1
2
3
gcc -o 123 123.c
./123
kill -SIGUSR1 3632

126

1
2
3
vim my_script.sh
/challenge/embryoio_level126
touch 126.py
1
2
3
4
5
6
7
8
9
10
11
from pwn import *
p = process(["bash","my_script.sh"])
for i in range(500):

    output = p.recvuntil(b"CHALLENGE! Please send the solution for: ")
    number = p.recvuntil(b"\n").strip()
    result = eval(number)
    p.sendline(str(result))
print(p.recvuntil("CORRECT!").decode("utf-8"))

print(p.recvall(timeout=1).decode("utf-8"))
1
python3 126.py

这个开始运行之后要等一会,因为有500个运算式,所以要一点时间。详细思路见87

128

1
2
3
vim my_script.sh
/challenge/embryoio_level128
vim 128.py
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
from pwn import *
# import pwn
import re
import signal
import os
import time

p = process(["bash", "my_script.sh"])
# output = p.recvall(timeout=10).decode("utf-8")    # it have some problem
output = p.recvuntil(b"in exactly this order:").decode("utf-8")
# print(output)
pid_match = re.search(r"\(PID ([0-9]+)", output)
# print(pid_match)
text = p.recvuntil(b"]").decode("utf-8")
signals_match = re.findall(r"'(SIG\w+)'", text)
# print("======================================================")
# print(signals_match)
if pid_match and signals_match:
    pid = int(pid_match.group(1))
    print(pid)
    signals = signals_match
    # for ind, i in enumerate(signals):
    #     s = eval(f'signal.{i}')
    #     print(ind, i, s)
    #     os.kill(pid, s)
    #     # p.interactive()
    #     # p.recvall(timeout=1).decode("utf-8")
    #     p.recvuntil(b"Correct!")
    for signal_name in signals:
        s = getattr(signal, signal_name)
        # s = eval(f'signal.{signal_name}')
        print(pid,s)
        os.kill(pid,s)
        p.recvuntil(b"Correct!\n")
        # time.sleep(.1)   # it's unuseful!
        print("finish")
p.interactive()
1
python3 128.py

这道题卡了蛮久,主要一开始还是和前面一样固化思维使用的p.sendline()这种方法,后面经jdin佬提醒改用os.kill()方法。又遇到了执行不了几次os.kill()这个程序就会关闭的问题,一开始以为是timeout的问题,然后改timeout和加入time.sleep(.1)等方法,但是依然没有效果,在排查一遍后发现可能是因为recvcall这个方法,貌似在使用这个方法之后p会被关掉,所以改用尝试recvuntil方法,然后就成功了。代码中的getattreval(f'')都可以将字符串转化为signal库中的信号。

131

1
vim 131.py
1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
# p = subprocess.run(["/challenge/embryoio_level99"])
p = process(["/challenge/embryoio_level131"])
for i in range(500):
    output = p.recvuntil(b"CHALLENGE! Please send the solution for: ")
    print(output.decode("utf-8"))
    number = p.recvuntil(b"\n").strip()
    print(number.decode("utf-8"))
    result = eval(number)
    p.sendline(str(result))
    # print(p.recvuntil(b"CORRECT!".decode("utf-8")))
print(p.recvall(timeout=1).decode("utf-8"))
1
python3 131.py

133

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
from pwn import *
import re
import signal
import os
import time

p = process(["/challenge/embryoio_level133"])
output = p.recvuntil(b"in exactly this order:").decode("utf-8")
pid_match = re.search(r"\(PID ([0-9]+)", output)
text = p.recvuntil(b"]").decode("utf-8")
signals_match = re.findall(r"'(SIG\w+)'", text)

if pid_match and signals_match:
    pid = int(pid_match.group(1))
    print(pid)
    signals = signals_match
    # for ind, i in enumerate(signals):
    #     s = eval(f'signal.{i}')
    #     print(ind, i, s)
    #     os.kill(pid, s)
    #     # p.interactive()
    #     # p.recvall(timeout=1).decode("utf-8")
    #     p.recvuntil(b"Correct!")
    for signal_name in signals:
        s = getattr(signal, signal_name)
        # s = eval(f'signal.{signal_name}')
        print(pid,s)
        os.kill(pid,s)
        p.recvuntil(b"Correct!\n")
        # time.sleep(.1)   # it's unuseful!
        print("finish")

p.interactive()
1
python3 133.py

这道题和128基本一样,改一下p的内容就好了

136

1
vim 136.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void pwncollege(){}

int main(int *argc,char *argv[]){
    int pid = fork();
    if(pid == 0){
        char *argv[] = {"/challenge/embryoio_level136",NULL};
        execv(argv[0],argv);
    }else{
        waitpid(pid,NULL,0);
    }
    return 0;
}
1
2
gcc -o 136 136.c
vim 136.py
1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

p = process(["./136"])

for i in range(500):
    output = p.recvuntil(b"CHALLENGE! Please send the solution for: ")
    number = p.recvuntil(b"\n").strip()
    result = eval(number)
    print(result)
    p.sendline(str(result))
print(p.recvuntil("CORRECT!").decode("utf-8"))

print(p.recvall(timeout=1).decode("utf-8"))
1
python3 136.py
  • 完全用C语言实现一整个逻辑
    这里先用C文件解决运行环境的问题,然后在python中运行C文件然后拿到算术式计算结果发送给程序就可以了,112 113这两道题目都可以这样解决。

138

1
vim 138.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void pwncollege(){}

int main(int *argc,char *argv[]){
    int pid = fork();
    if(pid == 0){
        char *argv[] = {"/challenge/embryoio_level136",NULL};
        execv(argv[0],argv);
    }else{
        waitpid(pid,NULL,0);
    }
    return 0;
}
1
2
gcc -o 138 138.c
vim 138.py
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
from pwn import *
import re
import signal
import os
p = process(["./138"])

output = p.recvuntil(b"in exactly this order:").decode("utf-8")

pid_match = re.search(r"\(PID ([0-9]+)", output)

text = p.recvuntil(b"]").decode("utf-8")

signals_match = re.findall(r"'(SIG\w+)'", text)

if pid_match and signals_match:
    pid = int(pid_match.group(1))
    print(pid)
    signals = signals_match
    for ind, i in enumerate(signals):
        s = eval(f'signal.{i}')
        # s = getattr(signal, signal_name)
        print(ind, i, s)
        os.kill(pid, s)
        p.recvuntil(b"Correct!")
p.interactive()
1
python3 138.py

这道题目和136思路是一样的

140


代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
HOST="localhost"
PORT=1294

exec 3<>/dev/tcp/${HOST}/${PORT}

# 启动一个后台进程,从端口读取数据并显示在终端上
while IFS= read -r line <&3; do
    echo "Received: $line"
done &

# 从终端读取输入并发送到端口
while :; do
    read -p "Enter input: " user_input
    if [[ -z "$user_input" ]]; then
        break
    fi
    echo "$user_input" >&3
done
exec 3<&-

这里用不了nc命令,所以让gpt自己写了一个socket连接拿来用,学到了怎么使用bash写一个socket连接了

141


先贴一张运行图,防止以后自己不记得怎么操作的了

上面这种方法是:

先开一个终端运行/challenge/embryoio_level141,然后运行python脚本,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *

p = remote("localhost",1229)
for i in range(5):
    output = p.recvuntil(b"CHALLENGE! Please send the solution for: ")
    number = p.recvuntil(b"\n").strip()
    print(number)
    result = eval(number)
    print(result)
    p.sendline(str(result))
print(p.recvuntil("CORRECT!").decode("utf-8"))
p.interactive()

使用remote方法来获取程序指定端口1229的输出,然后按照以前的计算逻辑编写剩下来的计算就好了。
这题难点主要是获取程序的输出,因为它是通过网络输出在1229的端口上的,最开始我想的是通过socket去获取输出,然后提取算术式并发送回结果,但是这样并不好去提取表达式,正则非常难写,而且发送结果那个步骤也很奇怪,尝试了几种方法都不能正确将结果发送回程序中并进行下一步,后翻阅pwntools的官方文档发现有remote方法,于是尝试了一下就写出来了

下面是全部逻辑都在一个脚本中方法:
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
from pwn import *
import multiprocessing
import subprocess
import time

# 1.
# def run_challenge_program():
#     k = process("/challenge/embryoio_level141")
#     k.wait()
# # 在子进程中运行外部程序
# challenge_process = multiprocessing.Process(target=run_challenge_program)
# challenge_process.start()


# 2.
k = process(["/challenge/embryoio_level141"])
challenge_process = multiprocessing.Process(target=process, args=("/challenge/embryoio_level141",))
k.wait()  # 等待进程完成
challenge_process.start()


# 3.
# challenge_process = subprocess.Popen(["/challenge/embryoio_level141"])

time.sleep(2)
p = remote("localhost", 1229)

for i in range(5):
    output = p.recvuntil(b"CHALLENGE! Please send the solution for: ")
    expression = p.recvuntil(b"\n").strip().decode()
    print(expression)
    result = eval(expression)
    print(result)
    p.sendline(str(result))
final_output = p.recv().decode()
print(final_output)

#challenge_process.join()等待子进程完成,类似waitpid() 1和2需要添加这个,3不需要
# challenge_process.join()

p.interactive()

这份代码里的三种方法其实思路都差不多,把运行/challenge/embryoio_level141也写进代码中,但是需要注意不能直接process(["/challenge/embryoio_level141"]),这样因为后续没有对这个进程进行操作,所以它会直接结束,在后面加interactive()也不行,因此要以子进程的形式去运行,challenge_process = subprocess.Popen(["/challenge/embryoio_level141"])这个可以运行也表示了这个挑战并不是和以前一样要求在python中运行/challenge,而是要在要求的语言中去获取端口中的输出信息并进行处理

142


下面是代码:

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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

#define PORT 1858
#define SIZE 1024

void pwncollege(){
    return;
}

int ainb(char* a,char* b){
    long unsigned int len1=strlen(a);
    long unsigned int len2=strlen(b);
    //printf("len(a):%ld\n",len1);
    //printf("len(b):%ld\n",len2);
    if(len1>len2) return 0;
    int xflag=0;
    for(int i=0;i<len2-len1;i++){
        if(strncmp(a,b+i,len1)==0){
            xflag=1;
            break;
        }
    }
    return xflag;
}

int main(int argc,char* argv[],char* env[])
{
    int client_socket = socket(AF_INET, SOCK_STREAM, 0);   //创建和服务器连接套接字
    if(client_socket == -1)
    {
        perror("socket");
        return -1;
    }
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;  /* Internet地址族 */
    addr.sin_port = htons(PORT);  /* 端口号 */
    addr.sin_addr.s_addr = htonl(INADDR_ANY);   /* IP地址 */
    inet_aton("127.0.0.1", &(addr.sin_addr));

    int addrlen = sizeof(addr);
    int listen_socket =  connect(client_socket,  (struct sockaddr *)&addr, addrlen);  //连接服务器
    if(listen_socket == -1)
    {
        perror("connect");
        return -1;
    }
    printf("成功连接到一个服务器\n");
    char buf[SIZE] = {0};
    int ret;
    while(1)        //向服务器发送数据,并接收服务器转换后的大写字母
    {
        //读取服务器内容
        //int ret = read(client_socket, buf, strlen(buf));
        while(1){
            memset(buf, 0, SIZE);//每次读取前重置
            ret = read(client_socket, buf, SIZE);
            printf("ret = %d\n", ret);
            if(0>=ret) break;
            printf("buf = %s", buf);
            printf("\n");
            if(1==ainb("Please send the solution for: ",buf))
            {
                break;
            }
        }
        printf("请输入你要输入的:");
        scanf("%s", buf);
        write(client_socket, buf, strlen(buf));
        write(client_socket, "\n", 1);
    }
    close(listen_socket);
    return 0;
}

这里就是用C语言实现了一个socket连接,然后获取输出,再手动计算结果(因为C语言的计算写起来很复杂)输入给程序,最后运行完成获得flag

  • Title: Program Interaction
  • Author: starlitxiling
  • Created at : 2023-10-26 23:05:31
  • Updated at : 2024-07-18 14:31:13
  • Link: http://starlitxiling.github.io/2023/10/26/Interaction/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments