私のラップトップで直接動的分析のためにusermode cプログラムでインラインで短い不明な(30行)アセンブリスクリプトを実行しない理由はありますか?
時間へのシステムコールは1つしかありません。この時点で、これはC文字列と長さを受け取り、ループ内で何らかの暗号化を実行する関数であることがわかります。これは、長さだけ文字列を反復するだけです。引数はそれを伝えます。
スクリプトが悪意のあるコードの一部であると考えられていることは知っていますが、私が生活している間、コンピューターが何らかのハードウェアのバグを排除する可能性があるとは考えられません(これは、ループの長さは7命令までで、スクリプト全体で最も奇妙な命令はshrです)。
未知のアセンブリコードを金属上で直接実行するのは悪いことのように聞こえますが、この時点までの私の分析を考えると、私を噛んだり、逃れたりする方法を考えることはできません。
コードを学習できない理由はありますか? ASMの30行は理解しやすいはずです。各行の機能を説明するコメントを追加するだけで、すぐに理解できます。これは、個々の命令の実行内容を正確にすばやく検索できるため、さらに簡単になります。
1回のシステムコールだけでは危険なことを単独で実行できる可能性は低いと私は同意しますが、一部の開発者が持つことができる独創性を過小評価してはなりません。数年前のDEF CONの講演で指摘されているように、逆アセンブラをだまして実際にはないコードを表示するようにシェルコードを設計することは完全に可能です。 30行のx86アセンブリは、ステージ1ペイロードに対して十分です。
おそらくそれは完全に無害です。とはいえ、自分の人生に賭けることはありません。
Linuxでseccompを使用してそれを分離できます。 Seccompは、システムコールをフィルタリングするLinuxの機能です。 seccompには、モード1とモード2の2つのモードがあります。Seccompモード1は、最も厳密なモードです。プログラムがこのモードを有効にする場合、使用できるのは4つだけに制限されます ハードコードされたsyscalls :read()
、write()
、exit()
、および- rt_sigreturn()
。モード2はより複雑で、ユーザースペースで生成されたeBPFフィルターを使用して、syscallsおよびsyscall引数のカスタムホワイトリストを指定します。非常に単純なシェルコードの場合、必要なのはモード1だけです。
モード1 seccompのアクティブ化は簡単です。バイトコードで42を返す関数を安全に実行するサンプルプログラムである別のStackExchangeサイトに書いた別の回答から引用します。
_#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <linux/seccomp.h>
/* "mov al,42; ret" aka "return 42" */
static const unsigned char code[] = "\xb0\x2a\xc3";
void main(void)
{
int fd[2], ret;
/* spawn child process, connected by a pipe */
pipe(fd);
if (fork() == 0) {
close(fd[0]);
/* enter mode 1 seccomp and execute untrusted bytecode */
prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
ret = (*(uint8_t(*)())code)();
/* send result over pipe, and exit */
write(fd[1], &ret, sizeof(ret));
syscall(SYS_exit, 0);
} else {
close(fd[1]);
/* read the result from the pipe, and print it */
read(fd[0], &ret, sizeof(ret));
printf("untrusted bytecode returned %d\n", ret);
}
}
_
_code[]
_をテストするシェルコードに置き換えます。
time()
へのsyscallが1つあるとおっしゃいました。ほとんどのLinuxシステムでは、これは本当のsyscallではなく、 vDSO です。実際に直接システムコールである場合は、モード2 seccompを使用して、明示的にホワイトリストに登録する必要があります。そのためには、 libseccomp を使用して複雑さを抽象化します。