{"id":2548,"date":"2023-10-24T11:54:58","date_gmt":"2023-10-24T09:54:58","guid":{"rendered":"https:\/\/security.humanativaspa.it\/?p=2548"},"modified":"2025-09-15T13:24:23","modified_gmt":"2025-09-15T13:24:23","slug":"customizing-sliver-part-3","status":"publish","type":"post","link":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/","title":{"rendered":"Customizing Sliver &#8211; Part 3"},"content":{"rendered":"<p class=\"graf graf--p\">In this third and final post in the <a href=\"https:\/\/hnsecurity.it\/tag\/sliver\/\">series<\/a> about <a href=\"https:\/\/github.com\/BishopFox\/sliver\">Sliver C2<\/a> I\u2019ll provide a tutorial for creating a simple command, named <em>helloworld<\/em>, that will take some parameters in input, send them to the implant, and then print back a string coming from the implant. You can find the <strong class=\"markup--strong markup--p-strong\">full code<\/strong>\u00a0implementing the <em>helloworld<\/em> command <a href=\"https:\/\/github.com\/MrAle98\/sliver\/tree\/hello_world\">here<\/a> at the <strong class=\"markup--strong markup--p-strong\">branch hello_world <\/strong>of my fork of Sliver.<\/p>\n<h2 class=\"graf graf--h3\">Creating the Hello World command<\/h2>\n<p class=\"graf graf--p\">The process for creating the command can be split in three phases:<\/p>\n<ol class=\"postList\">\n<li class=\"graf graf--li\">Define protobuf messages for server, client, and implant in sliver.proto\/client.proto and the rpc functions inside services.proto.<\/li>\n<li class=\"graf graf--li\">Develop\/debug the interaction betweeen client-side command and server handler.<\/li>\n<li class=\"graf graf--li\">Develop the implant handler and debug all the flow.<\/li>\n<\/ol>\n<h3 class=\"graf graf--h4\">Defining protobuf messages<\/h3>\n<p class=\"graf graf--p\">First of all, we need to define the format of requests and responses that will be exchanged during client-server interaction and server-implant interaction, and the gRPC function for client-server communication.<\/p>\n<p class=\"graf graf--p\">Here are the definitions in sliver.proto and services.proto:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">sliver.proto\r\n...\r\n...\r\nmessage HelloWorldReq {\r\n  string param1 = 1;\r\n  uint32 param2 = 2;\r\n  bool param3 = 3;\r\ncommonpb.Request Request = 9;\r\n}\r\nmessage HelloWorld {\r\n  string output = 1;\r\n  commonpb.Response Response = 9;\r\n}\r\n...\r\n...\r\n-------------------------------------------\r\nservices.proto\r\n...\r\n...\r\n\/\/ *** Hello World ***\r\nrpc HelloWorld(sliverpb.HelloWorldReq) returns (sliverpb.HelloWorld);<\/pre>\n<p class=\"graf graf--p\">The <strong class=\"markup--strong markup--p-strong\">request is HelloWorldReq<\/strong> and contains a string, a uint32, and a boolean field. In addition, it embeds commonpb.Request as all the other request messages in the file.<\/p>\n<p class=\"graf graf--p\">The <strong class=\"markup--strong markup--p-strong\">response is HelloWorld <\/strong>and contains just a string. In addition it embeds commonpb.Response as all the other response messages in the file.<\/p>\n<p class=\"graf graf--p\">You can give a look at the other messages in order to find more field types that you can embed in your messages.<\/p>\n<p class=\"graf graf--p\">Finally, in services.proto we defined the<strong class=\"markup--strong markup--p-strong\"> gRPC function HelloWorld<\/strong> that takes as input a <strong class=\"markup--strong markup--p-strong\">sliverpb.HelloWorldReq<\/strong> message and returns a <strong class=\"markup--strong markup--p-strong\">sliverpb.HelloWorld<\/strong> message, the ones defined in sliverpb.proto.<\/p>\n<p class=\"graf graf--p\">Now, run the command <em>make pb<\/em> in a terminal under the sliver main folder:<\/p>\n<div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\">\u250c\u2500\u2500(kali\u327fkali)-[~\/sliver]\r\n\u2514\u2500$\u00a0make\u00a0pb\r\nprotoc\u00a0-I\u00a0protobuf\/\u00a0protobuf\/commonpb\/common.proto\u00a0--go_out=paths=source_relative:protobuf\/\r\nprotoc\u00a0-I\u00a0protobuf\/\u00a0protobuf\/sliverpb\/sliver.proto\u00a0--go_out=paths=source_relative:protobuf\/\r\nprotoc\u00a0-I\u00a0protobuf\/\u00a0protobuf\/clientpb\/client.proto\u00a0--go_out=paths=source_relative:protobuf\/\r\nprotoc\u00a0-I\u00a0protobuf\/\u00a0protobuf\/dnspb\/dns.proto\u00a0--go_out=paths=source_relative:protobuf\/\r\nprotoc\u00a0-I\u00a0protobuf\/\u00a0protobuf\/rpcpb\/services.proto\u00a0--go_out=paths=source_relative:protobuf\/\u00a0--go-grpc_out=protobuf\/\u00a0--go-grpc_opt=paths=source_relative\u00a0\r\n\u250c\u2500\u2500(kali\u327fkali)-[~\/sliver]\r\n\u2514\u2500$<\/pre>\n<p>This is going to rebuild all the go files under the protobuf folder such as sliver.pb.go, client.pb.go, and so on. By now they contain the go struct and functions corresponding to messages and gRPC functions previously defined. You can browse to <strong class=\"markup--strong markup--p-strong\">protobuf\/sliver.pb.go <\/strong>in order to notice that now a <strong class=\"markup--strong markup--p-strong\">HelloWorldReq struct<\/strong> is present with associated methods.<\/p>\n<\/div>\n<\/div>\n<figure class=\"graf graf--figure\">\n<p><figure style=\"width: 1000px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"graf-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*RQP1mCDOLQ1V6L29CMPQww.png\" alt=\"\" width=\"1000\" height=\"502\" data-image-id=\"1*RQP1mCDOLQ1V6L29CMPQww.png\" data-width=\"1207\" data-height=\"606\" \/><figcaption class=\"wp-caption-text\">The sliver.pb.go file containing HelloWorldReq<\/figcaption><\/figure><\/figure>\n<h3 class=\"graf graf--h4\">Developing the client-side command<\/h3>\n<p class=\"graf graf--p\">Here we are going to define a new HelloWorld command in the client component of the framework. First, we need to add the command definition in <a href=\"https:\/\/github.com\/MrAle98\/sliver\/blob\/hello_world\/client\/command\/sliver.go\">client\/command\/sliver.go<\/a>. Here&#8217;s the definition I\u2019ve written:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">\/\/ [ Hello World] ------------------------------------------\r\n  helloWorldCmd := &amp;cobra.Command{\r\n   Use:   consts.HelloWorldStr,\r\n   Short: \"Hello World command\",\r\n   Long:  help.GetHelpFor([]string{consts.HelloWorldStr}),\r\n   Args:  cobra.ExactArgs(1),\r\n   Run: func(cmd *cobra.Command, args []string) {\r\n    helloworld.HelloWorldCmd(cmd, con, args)\r\n   },\r\n   GroupID: consts.FilesystemHelpGroup,\r\n  }\r\n  sliver.AddCommand(helloWorldCmd)\r\n  Flags(\"\", false, helloWorldCmd, func(f *pflag.FlagSet) {\r\n   f.Uint32P(\"intflag\", \"i\", 0, \"parameter 2\")\r\n   f.BoolP(\"boolflag\", \"x\", false, \"parameter 3\")\r\n   f.Int64P(\"timeout\", \"t\", defaultTimeout, \"grpc timeout in seconds\")\r\n  })\r\n  carapace.Gen(helloWorldCmd).PositionalCompletion(\r\n   carapace.ActionValues().Usage(\"parameter1\")\r\n  )<\/pre>\n<p class=\"graf graf--p\">First I created a cobra.Command struct having with the following fields:<\/p>\n<ul class=\"postList\">\n<li class=\"graf graf--li\">Use: set to <strong class=\"markup--strong markup--li-strong\">consts.HelloWorldStr<\/strong>. This is a string I defined inside <strong class=\"markup--strong markup--li-strong\">client\/constants\/constants.go <\/strong>in this way: <code class=\"markup--code markup--li-code\">HelloWorldStr = \"helloworld\"<\/code><\/li>\n<li class=\"graf graf--li\">Short: another string<\/li>\n<li class=\"graf graf--li\">Long: the full description of the command. In <strong class=\"markup--strong markup--li-strong\">client\/help\/long-help.go<\/strong> add the entry <code class=\"markup--code markup--li-code\">consts.HelloWorldStr: helloWorldHelp<\/code>to the map <code class=\"markup--code markup--li-code\">cmdHelp<\/code>, and add the string <code class=\"markup--code markup--li-code\">helloWorldHelp<\/code> containing the full help for the command.<\/li>\n<li class=\"graf graf--li\">Run: contains a callback that calls <code class=\"markup--code markup--li-code\">helloworld.HelloWorldCmd()<\/code> . This is the function that will actually send the request to the server and print the response. We will define it later.<\/li>\n<\/ul>\n<p class=\"graf graf--p\">Then I added the command and I defined two flags for the command. A boolean flag <code class=\"markup--code markup--p-code\">-X<\/code> and a timeout flag <code class=\"markup--code markup--p-code\">-t<\/code> (timeout is present in all commands).<\/p>\n<p class=\"graf graf--p\">I\u2019m not sure about what the last part involving the carapace library does, but I think that BishopFox added it quite recently to improve user experience. I just copy\/pasted it from another command and then modified the relevant parts.<\/p>\n<p class=\"graf graf--p\">At the end, the <strong class=\"markup--strong markup--p-strong\">helloworld <\/strong>command takes as input <strong class=\"markup--strong markup--p-strong\">one positional parameter in the form of string<\/strong>, and<strong class=\"markup--strong markup--p-strong\"> three flags<\/strong>:\u00a0an <strong class=\"markup--strong markup--p-strong\">integer<\/strong>, a <strong class=\"markup--strong markup--p-strong\">boolean<\/strong>, and <strong>another integer<\/strong> indicating a timeout. The <strong class=\"markup--strong markup--p-strong\">boolean and the integer will be embedded in the request<\/strong> sent to the server, just for showing how to pass data through flags to the server and eventually to the implant.<\/p>\n<p class=\"graf graf--p\">Now it is required to define the function helloworld.HelloWorldCmd(). In order to do this I\u2019ll create a folder called <strong class=\"markup--strong markup--p-strong\">helloworld <\/strong>under <strong class=\"markup--strong markup--p-strong\">client\/command<\/strong> and inside it, I will create a source file named <a href=\"https:\/\/github.com\/MrAle98\/sliver\/blob\/hello_world\/client\/command\/helloworld\/helloworld.go\">helloworld.go<\/a> containing the definition of helloworld.HelloWorldCmd() and the package <strong class=\"markup--strong markup--p-strong\">helloworld<\/strong>.<\/p>\n<p class=\"graf graf--p\">The contents of my <strong class=\"markup--strong markup--p-strong\">helloworld.go<\/strong>\u00a0are:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">package helloworld\r\n\r\nimport (\r\n ...\r\n...\r\n)\r\nfunc HelloWorldCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) (err error) {\r\n session, beacon := con.ActiveTarget.GetInteractive()\r\n if session == nil &amp;&amp; beacon == nil {\r\n  return\r\n }\r\n if len(args) != 1 {\r\n  con.PrintErrorf(\"Please specify an argument for param1.\\n\")\r\n  return\r\n }\r\n param1 := args[0]\r\n param2, _ := cmd.Flags().GetUint32(\"intflag\")\r\n param3, _ := cmd.Flags().GetBool(\"boolflag\")\r\n out, err := con.Rpc.HelloWorld(context.Background(), &amp;sliverpb.HelloWorldReq{\r\n  Request: con.ActiveTarget.Request(cmd),\r\n  Param1:  param1,\r\n  Param2:  param2,\r\n  Param3:  param3,\r\n })\r\n if err != nil {\r\n  con.PrintErrorf(\"%s\\n\", err)\r\n  return\r\n }\r\n if out.Response != nil &amp;&amp; out.Response.Async {\r\n  con.AddBeaconCallback(out.Response.TaskID, func(task *clientpb.BeaconTask) {\r\n   err = proto.Unmarshal(task.Response, out)\r\n   if err != nil {\r\n    con.PrintErrorf(\"Failed to decode response %s\\n\", err)\r\n    return\r\n   }\r\n   PrintHelloWorld(out,con)\r\n  })\r\n  con.PrintAsyncResponse(out.Response)\r\n } else {\r\n  PrintHelloWorld(out, con)\r\n }\r\n return\r\n}\r\nfunc PrintHelloWorld(hw *sliverpb.HelloWorld, con *console.SliverConsoleClient) {\r\n if hw.Response != nil &amp;&amp; hw.Response.Err != \"\" {\r\n  con.PrintErrorf(\"%s\\n\", hw.Response.Err)\r\n  return\r\n }\r\n con.PrintInfof(\"Here the output coming from the implant: %s\\n\", hw.Output)\r\n}<\/pre>\n<p class=\"graf graf--p\">In HelloWorldCmd I just take the 3 parameters: <strong class=\"markup--strong markup--p-strong\">args[0]<\/strong> the string passed as positional parameter, the integer flag <strong class=\"markup--strong markup--p-strong\">cmd.Flags().GetUint32(\u201cintflag\u201d)<\/strong>, and the boolean flag <strong class=\"markup--strong markup--p-strong\">cmd.Flags().GetBool(\u201cboolflag\u201d)<\/strong>. Then I create the <strong class=\"markup--strong markup--p-strong\">HelloWorldReq struct<\/strong>, populate its fields with the parameters and send the request to the server calling<strong class=\"markup--strong markup--p-strong\"> con.Rpc.HelloWorld().<\/strong><\/p>\n<p class=\"graf graf--p\">Later there are some if statements checking if the request is for a beacon or for a session. In both cases we are going to execute <strong class=\"markup--strong markup--p-strong\">PrintHelloWorld() <\/strong>to print the result coming from the server.<\/p>\n<p class=\"graf graf--p\">Finally, go back to <strong class=\"markup--strong markup--p-strong\">sliver.go<\/strong> and add the import <strong class=\"markup--strong markup--p-strong\">\u201cgithub.com\/bishopfox\/sliver\/client\/command\/helloworld\u201d<\/strong>, in case VSCode doesn&#8217;t automatically adds it for you, after saving all files.<\/p>\n<p class=\"graf graf--p\">Now we will define the server-side handler for our HelloWorldReq request. We can create <a href=\"https:\/\/github.com\/MrAle98\/sliver\/blob\/hello_world\/server\/rpc\/rpc-helloworld.go\">server\/rpc\/rpc-helloworld.go<\/a> and define here the handler, in order to be coherent with the project structure.<\/p>\n<p class=\"graf graf--p\">The contents of my <strong>rpc-helloworld.go<\/strong> file are:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">package rpc\r\n\r\nimport (\r\n \"context\"\r\n \"github.com\/bishopfox\/sliver\/protobuf\/commonpb\"\r\n \"github.com\/bishopfox\/sliver\/protobuf\/sliverpb\"\r\n)\r\n\/\/ HelloWorld - HelloWorld command\r\nfunc (rpc *Server) HelloWorld(ctx context.Context, req *sliverpb.HelloWorldReq) (*sliverpb.HelloWorld, error) {\r\n resp := &amp;sliverpb.HelloWorld{Response: &amp;commonpb.Response{}}\r\n err := rpc.GenericHandler(req, resp)\r\n if err != nil {\r\n  return nil, err\r\n }\r\n return resp, nil\r\n}<\/pre>\n<p class=\"graf graf--p\">The defined function falls under the rpc package. As defined in <strong class=\"markup--strong markup--p-strong\">services.proto<\/strong>, <strong class=\"markup--strong markup--p-strong\">HelloWorld() <\/strong>is our function handling the request server-side; it\u00a0takes as input a struct of type <strong class=\"markup--strong markup--p-strong\">sliverpb.HelloWorldReq<\/strong> and returns a struct of type <strong class=\"markup--strong markup--p-strong\">sliverpb.HelloWorld<\/strong>. We defined the structs previously in sliverpb.proto.<\/p>\n<p class=\"graf graf--p\"><em class=\"markup--em markup--p-em\">If you are unsure about what the signature of the function you have to define should be, I suggest you to take a simple rpc handler function, such as <\/em><strong class=\"markup--strong markup--p-strong\"><em class=\"markup--em markup--p-em\">Ls(),<\/em><\/strong><em class=\"markup--em markup--p-em\"> defined in <\/em><strong class=\"markup--strong markup--p-strong\"><em class=\"markup--em markup--p-em\">rpc-filesystem<\/em><\/strong><em class=\"markup--em markup--p-em\">, and modify it accordingly, by checking your definitions inside services.proto\/sliver.proto.<\/em><\/p>\n<p class=\"graf graf--p\">The function simply creates a <strong class=\"markup--strong markup--p-strong\">struct of type sliverpb.HelloWorld<\/strong>, stores it in the <strong class=\"markup--strong markup--p-strong\">resp<\/strong> variable and then calls<strong class=\"markup--strong markup--p-strong\"> rpc.GenericHandler()<\/strong> passing the initial request coming from the client and the resp variable. When rpc.GenericHandler() returns, we will find <strong class=\"markup--strong markup--p-strong\">the response from the implant in the resp variable<\/strong>. Therefore, resp is returned to the caller with the <code class=\"markup--code markup--p-code\">return resp, nil<\/code> statement, and finally sent to the client.<\/p>\n<p class=\"graf graf--p\">Let\u2019s debug what we have done so far in order to check that the client successfully sends the request to the server.<\/p>\n<h3 class=\"graf graf--h4\">Debugging client-server interaction<\/h3>\n<p class=\"graf graf--p\">You must first launch both client and server in debug mode, inside VSCode, as shown in <a href=\"https:\/\/hnsecurity.it\/customizing-sliver-part-1\/\">part 1<\/a>, Setting up the Environment section.<\/p>\n<p class=\"graf graf--p\">Then just create an implant, move it to your Windows machine and run it.<\/p>\n<p class=\"graf graf--p\">When you receive the callback from the implant, interact with it and check that the helloworld command is available.<\/p>\n<figure class=\"graf graf--figure\">\n<p><figure style=\"width: 1000px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"graf-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*nZXil29MTzXDgAgJSDTlmA.png\" alt=\"\" width=\"1000\" height=\"171\" data-image-id=\"1*nZXil29MTzXDgAgJSDTlmA.png\" data-width=\"1199\" data-height=\"205\" \/><figcaption class=\"wp-caption-text\">Running helloworld<\/figcaption><\/figure><\/figure>\n<p class=\"graf graf--p\">Now put a breakpoint on HelloWorldCmd() in the client and on HelloWorld() in the server. Then run your newly created helloworld command like this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">&gt; helloworld -i 30 -x firstparam<\/pre>\n<p class=\"graf graf--p\">You should see the first breakpoint on HelloWorldCmd() got hit.<\/p>\n<figure class=\"graf graf--figure\">\n<p><figure style=\"width: 1000px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"graf-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*o4OirgDRIX_0wUBiqumo0w.png\" alt=\"\" width=\"1000\" height=\"531\" data-image-id=\"1*o4OirgDRIX_0wUBiqumo0w.png\" data-width=\"1588\" data-height=\"843\" \/><figcaption class=\"wp-caption-text\">First breakpoint<\/figcaption><\/figure><\/figure>\n<p class=\"graf graf--p\">Stepping with the debugger you should reach the second breakpoint on the server.<\/p>\n<figure class=\"graf graf--figure\">\n<p><figure style=\"width: 1000px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"graf-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*dRUiN9TPZcCWSuhZ_ZW2cA.png\" alt=\"\" width=\"1000\" height=\"535\" data-image-id=\"1*dRUiN9TPZcCWSuhZ_ZW2cA.png\" data-width=\"1586\" data-height=\"848\" \/><figcaption class=\"wp-caption-text\">Second breakpoint<\/figcaption><\/figure><\/figure>\n<p class=\"graf graf--p\">Notice, with the help of the right upper pane, that the <strong class=\"markup--strong markup--p-strong\">req parameter contains param1, param2, and param3 <\/strong>with the <strong class=\"markup--strong markup--p-strong\">values sent through the command line<\/strong>.<\/p>\n<p class=\"graf graf--p\">We managed to create a command that sends a request from the client to the server. In the the next phase we are going to let the server forward the request to the implant, and the implant will process the request and answer to the server.<\/p>\n<h3 class=\"graf graf--h4\">Developing the implant\u00a0handler<\/h3>\n<p class=\"graf graf--p\">In this phase we will customize the implant, by defining a handler function that is in charge of handling the HelloWorldReq message coming from the server.<\/p>\n<p class=\"graf graf--p\">In order to do that, move to the folder containing the source code of one of your generated implants (recall from <a href=\"https:\/\/hnsecurity.it\/customizing-sliver-part-1\/\">part 1<\/a> that the folder is of type ~\/.sliver\/slivers\/windows\/amd64\/&lt;IMPLANT_NAME&gt;\/src) and add the .vscode folder as shown in <a href=\"https:\/\/hnsecurity.it\/customizing-sliver-part-1\/\">part 1<\/a>. Finally, open the folder in VSCode.<\/p>\n<p class=\"graf graf--p\">We are going to add our handler function in <a href=\"https:\/\/github.com\/MrAle98\/sliver\/blob\/hello_world\/implant\/sliver\/handlers\/handlers.go#L449\">implant\/sliver\/handlers\/handlers.go<\/a>. Since the HelloWorld task can be executed on any OS, we can place our handler in handlers.go. On the other hand, if the task can be executed for example only on Windows, the handler should be placed in handlers_windows.go. The same applies to Linux and macOS as already outlined in <a href=\"https:\/\/hnsecurity.it\/customizing-sliver-part-2\/\">part 2<\/a>.<\/p>\n<p class=\"graf graf--p\">The code for the handler function is:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">func helloWorldHandler(data []byte, resp RPCResponse) {\r\n helloworldReq := &amp;sliverpb.HelloWorldReq{}\r\n err := proto.Unmarshal(data, helloworldReq)\r\n\r\nif err != nil {\r\n  \/\/\r\n  log.Printf(\"error decoding message: %v\", err)\r\n  \/\/\r\n  return\r\n }\r\n \/\/\r\n helloworldResp := &amp;sliverpb.HelloWorld{}\r\n p3 := \"\"\r\n if helloworldReq.Param3 {\r\n  p3 = \"FALSE\"\r\n } else {\r\n  p3 = \"TRUE\"\r\n }\r\n helloworldResp.Output = fmt.Sprintf(\"I'm your implant and i received the following:\\nparam1: %s\\nparam2: %d\\nparam3: %s\",\r\n  helloworldReq.Param1, helloworldReq.Param2, p3)\r\n \/\/log.Printf(\"ping id = %d\", ping.Nonce)\r\n \/\/\r\n data, err = proto.Marshal(helloworldResp)\r\n resp(data, err)\r\n}<\/pre>\n<p class=\"graf graf--p\">The function simply <strong class=\"markup--strong markup--p-strong\">unserializes the incoming data request in the sliverpb.HelloWorldReq struct<\/strong>, then <strong class=\"markup--strong markup--p-strong\">creates the sliverpb.HelloWorld struct that will store the response<\/strong>.<\/p>\n<p class=\"graf graf--p\">In helloworldResp.Output I just store a string that shows the data received in the request. This will be printed on console client-side.<\/p>\n<p class=\"graf graf--p\">Finally, I <strong class=\"markup--strong markup--p-strong\">serialize the response helloworldResp<\/strong> and <strong class=\"markup--strong markup--p-strong\">invoke the callback resp()<\/strong> in order to send the response back to the C2 server.<\/p>\n<p class=\"graf graf--p\">Lastly, we need to <strong class=\"markup--strong markup--p-strong\">add our handler to the list of handlers in a map<\/strong>. This is required so that the implant, during the main loop, will invoke our handler when required. Since this is a \u201cgeneric\u201d handler, meaning that the implant can get executed on any OS, we can add our handler to the map <strong class=\"markup--strong markup--p-strong\">systemHandlers<\/strong>, where <strong class=\"markup--strong markup--p-strong\"><a href=\"https:\/\/github.com\/MrAle98\/sliver\/blob\/hello_world\/implant\/sliver\/handlers\/handlers_windows.go#L52C1-L52C1\">handlers_windows.go<\/a>, handler_linux.go, and handlers_darwin.go define systemHandlers<\/strong>.<\/p>\n<p class=\"graf graf--p\">So I\u2019ll add the following entry to the handlers map in the three files already mentioned:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">sliverpb.MsgHelloWorldReq: helloWorldHandler,<\/pre>\n<p class=\"graf graf--p\">As shown in the screenshot:<\/p>\n<figure class=\"graf graf--figure\">\n<p><figure style=\"width: 1000px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"graf-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*ktF6YMDG9U8sv84fJG4h5Q.png\" alt=\"\" width=\"1000\" height=\"582\" data-image-id=\"1*ktF6YMDG9U8sv84fJG4h5Q.png\" data-width=\"1355\" data-height=\"788\" \/><figcaption class=\"wp-caption-text\">Adding handler to map<\/figcaption><\/figure><\/figure>\n<p class=\"graf graf--p\">Notice that we still have to define the uint32 <strong class=\"markup--strong markup--p-strong\">sliverpb.MsgHelloWorldReq. <\/strong>This must be defined in <a href=\"https:\/\/github.com\/MrAle98\/sliver\/blob\/hello_world\/protobuf\/sliverpb\/constants.go#L344\">protobuf\/sliverpb\/constants.go<\/a>.<\/p>\n<p class=\"graf graf--p\"><em class=\"markup--em markup--p-em\">You need to add the definition to <\/em><strong class=\"markup--strong markup--p-strong\"><em class=\"markup--em markup--p-em\">both the constants.go file in the sliver main folder and the implant folder<\/em><\/strong><em class=\"markup--em markup--p-em\">.<\/em><\/p>\n<p class=\"graf graf--p\">So here&#8217;s the updated <strong>constants.go<\/strong>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"golang\">package sliverpb\r\n\r\nimport (\r\n \"google.golang.org\/protobuf\/proto\"\r\n)\r\n...\r\n...\r\nconst (\r\n \/\/ MsgRegister - Initial message from sliver with metadata\r\n MsgRegister = uint32(1 + iota)\r\n \/\/ MsgTaskReq - A local shellcode injection task\r\n MsgTaskReq\r\n...\r\n...\r\n \/\/MsgHelloWorldReq\r\n MsgHelloWorldReq\r\n)\r\n...\r\n...\r\n\/\/ MsgNumber - Get a message number of type\r\nfunc MsgNumber(request proto.Message) uint32 {\r\n switch request.(type) {\r\n case *Register:\r\n  return MsgRegister\r\n...\r\n...\r\n case *HelloWorldReq:\r\n  return MsgHelloWorldReq\r\n}\r\n return uint32(0)\r\n}<\/pre>\n<p class=\"graf graf--p\">Basically I just added:<\/p>\n<ul class=\"postList\">\n<li class=\"graf graf--li\"><em class=\"markup--em markup--li-em\">MsgHelloWorldReq<\/em> <strong class=\"markup--strong markup--li-strong\">at the end <\/strong>of the first list of consts.<\/li>\n<li class=\"graf graf--li\">The <code class=\"markup--code markup--li-code\">case *HelloWorldReq<\/code> to the switch statement at the bottom.<\/li>\n<\/ul>\n<p class=\"graf graf--p\">Be careful to <strong>add the definition always <\/strong><strong class=\"markup--strong markup--p-strong\">at the end<\/strong>. In fact, the developers specified in constants.go, in the comment at the top, that <strong class=\"markup--strong markup--p-strong\">you can modify the constants by appending only<\/strong>.<\/p>\n<h3 class=\"graf graf--h4\">Rebuilding and debugging<\/h3>\n<p class=\"graf graf--p\">Now we have to rebuild our implant and start client, server, and implant in debug mode in order to check that everything works.<\/p>\n<p class=\"graf graf--p\">Let\u2019s first rebuild our implant. In our main implant folder let\u2019s move to src\/github.com\/bishopfox\/sliver (the folder containing sliver.go, main.go, and so on), and rebuild our implant issuing the following commands:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"bash\">\u250c\u2500\u2500(kali\u327fkali)-[~\/.sliver\/slivers\/windows\/amd64\/RUNNING_WEAKNESS\/src\/github.com\/bishopfox\/sliver]\r\n\u2514\u2500$ export GOOS=windows\r\n\u250c\u2500\u2500(kali\u327fkali)-[~\/.sliver\/slivers\/windows\/amd64\/RUNNING_WEAKNESS\/src\/github.com\/bishopfox\/sliver]\r\n\u2514\u2500$ \/home\/kali\/.sliver\/go\/bin\/go  build -trimpath -gcflags=all=-N  -o agent.exe .\r\n\r\n\u250c\u2500\u2500(kali\u327fkali)-[~\/.sliver\/slivers\/windows\/amd64\/RUNNING_WEAKNESS\/src\/github.com\/bishopfox\/sliver]\r\n\u2514\u2500$ ls\r\nagent.exe  go.mod  go.sum  implant  protobuf  sliver.go  vendor\r\n\u250c\u2500\u2500(kali\u327fkali)-[~\/.sliver\/slivers\/windows\/amd64\/RUNNING_WEAKNESS\/src\/github.com\/bishopfox\/sliver]\r\n\u2514\u2500$<\/pre>\n<p class=\"graf graf--p\">First I set the environment variable GOOS to the target running environment for the implant, in this case &#8220;windows&#8221;. Then I build the implant. In this case the final executable is named <strong class=\"markup--strong markup--p-strong\">agent.exe<\/strong>.<\/p>\n<p class=\"graf graf--p\">Now perform the following:<\/p>\n<ol>\n<li>in the VSCode window containing the sliver main folder, save all files and then restart server and client in debugging mode.<\/li>\n<li>move the agent.exe to your Windows machine, then run agent.exe with <strong class=\"markup--strong markup--li-strong\">dlv<\/strong> as shown during <a href=\"https:\/\/hnsecurity.it\/customizing-sliver-part-1\/\">part 1<\/a> (needed for debugging purposes).<\/li>\n<\/ol>\n<p class=\"graf graf--p\">Now that you are running everything in debugging mode, let\u2019s move to the VSCode window debugging the implant and let\u2019s put a breakpoint at <strong class=\"markup--strong markup--p-strong\">helloWorldHandler()<\/strong> in <strong class=\"markup--strong markup--p-strong\">handlers.go.<\/strong><\/p>\n<figure class=\"graf graf--figure\">\n<p><figure style=\"width: 1000px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"graf-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*Seh642GsSH1lXH6RD9dc2g.png\" alt=\"\" width=\"1000\" height=\"353\" data-image-id=\"1*Seh642GsSH1lXH6RD9dc2g.png\" data-width=\"1088\" data-height=\"384\" \/><figcaption class=\"wp-caption-text\">Breakpoint on helloWorldHandler<\/figcaption><\/figure><\/figure>\n<p class=\"graf graf--p\">Let\u2019s put an additional breakpoint on the client in <strong class=\"markup--strong markup--p-strong\">helloWorldCmd<\/strong> in <strong class=\"markup--strong markup--p-strong\">helloworld.go<\/strong>, at the line of code after calling conRpc.HelloWorld(). So, when reaching this breakpoint, the <strong class=\"markup--strong markup--p-strong\">out variable will contain the response from the implant<\/strong>.<\/p>\n<figure class=\"graf graf--figure\">\n<p><figure style=\"width: 1000px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"graf-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*d7pqGbBpkRYc8Ckdfj40FQ.png\" alt=\"\" width=\"1000\" height=\"401\" data-image-id=\"1*d7pqGbBpkRYc8Ckdfj40FQ.png\" data-width=\"1452\" data-height=\"582\" \/><figcaption class=\"wp-caption-text\">Breakpoint in helloWorldCmd<\/figcaption><\/figure><\/figure>\n<p class=\"graf graf--p\">Now let\u2019s move to the Sliver client console, select the agent session and run our newly created command this way:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">[*] Session 2b7aa1e7 RUNNING_WEAKNESS - 192.168.157.131:59650 (DESKTOP-URP43TK) - windows\/amd64 - Sun, 10 Sep 2023 22:27:26 CEST\r\n\r\nsliver (RUNNING_WEAKNESS) &gt; use 2b7\r\n[*] Active session RUNNING_WEAKNESS (2b7aa1e7-1b67-4174-a532-9ff9976a6df3)\r\nsliver (RUNNING_WEAKNESS) &gt; helloworld -x -i 30 myparam -t 4000<\/pre>\n<p class=\"graf graf--p\">After running the command you should hit the breakpoint at <strong>helloWorldHandler()<\/strong>. If you step through the code you can see what happens step by step.<\/p>\n<p class=\"graf graf--p\">Now, if you resume the execution, you should hit the second breakpoint on the client. The execution will finally land in <strong class=\"markup--strong markup--p-strong\">PrintHelloWorld() <\/strong>that prints the result coming from the implant, as you can see by looking at the Sliver client console.<\/p>\n<figure class=\"graf graf--figure\">\n<p><figure style=\"width: 1000px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" class=\"graf-image\" src=\"https:\/\/cdn-images-1.medium.com\/max\/1000\/1*9rfGv8jp6BwfQUW3Ewf00Q.png\" alt=\"\" width=\"1000\" height=\"492\" data-image-id=\"1*9rfGv8jp6BwfQUW3Ewf00Q.png\" data-width=\"1237\" data-height=\"608\" \/><figcaption class=\"wp-caption-text\">Output coming from the implant<\/figcaption><\/figure><\/figure>\n<p class=\"graf graf--p\">So you can see the implant successfully took parameters passed through the command-line and inserted them in a string that was sent back to the client. The client finally printed the string on the console.<\/p>\n<p class=\"graf graf--p\">Now that you tested your code on the implant-side, and it works successfully, you just need to insert your code under the sliver main folder at <em class=\"markup--em markup--p-em\">sliver\/implant\/sliver.<\/em><\/p>\n<p class=\"graf graf--p\">If you rebuild server and client with the <code class=\"markup--code markup--p-code\">make<\/code> command, as outlined <a href=\"https:\/\/github.com\/BishopFox\/sliver\/wiki\/Compile-From-Source#compile-from-source-no-docker\">here<\/a>, the server will generate implants that are able to process your helloworld command.<\/p>\n<p class=\"graf graf--p\">By now you should have an idea about how to add your own commands to Sliver C2!<\/p>\n<h4 class=\"graf graf--h4\">Exercise for the\u00a0reader<\/h4>\n<p class=\"graf graf--p\">Many C2s implement what is called a <strong class=\"markup--strong markup--p-strong\">token vault<\/strong>. You can think about it as an <strong class=\"markup--strong markup--p-strong\">array of token handles<\/strong>, stored in the implant process, obtained by calling <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/learn.microsoft.com\/it-it\/windows\/win32\/api\/securitybaseapi\/nf-securitybaseapi-duplicatetokenex\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/learn.microsoft.com\/it-it\/windows\/win32\/api\/securitybaseapi\/nf-securitybaseapi-duplicatetokenex\">DuplicateTokenEx()<\/a> on tokens assigned to other processes.<\/p>\n<p class=\"graf graf--p\">I leave as an exercise to the reader the implementation of the following commands:<\/p>\n<ul class=\"postList\">\n<li class=\"graf graf--li\"><em class=\"markup--em markup--li-em\">grab_token<\/em>: command that calls DuplicateTokenEx() on the process primary token and stores it in a map called <strong class=\"markup--strong markup--li-strong\">tokenVaultMap.<\/strong><\/li>\n<li class=\"graf graf--li\"><em class=\"markup--em markup--li-em\">list_token_vault<\/em>: command that lists tokens in the vault in the form of a map id\u200a-\u200atoken owner.<\/li>\n<li class=\"graf graf--li\"><em class=\"markup--em markup--li-em\">impersonate_token_vault<\/em>: command that impersonates a token in the vault given the id.<\/li>\n<li class=\"graf graf--li\"><em class=\"markup--em markup--li-em\">remove_token_vault<\/em>: command that removes a token from the vault given the id.<\/li>\n<\/ul>\n<p class=\"graf graf--p\">I encourage you to read the code defined under <a class=\"markup--anchor markup--p-anchor\" href=\"https:\/\/github.com\/BishopFox\/sliver\/tree\/master\/implant\/sliver\/priv\" target=\"_blank\" rel=\"noopener\" data-href=\"https:\/\/github.com\/BishopFox\/sliver\/tree\/master\/implant\/sliver\/priv\">sliver\/implant\/sliver\/priv<\/a> to understand token management in Sliver C2 implants. That&#8217;s all for now, thank you for reading!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this third and final post in the series about Sliver C2 I\u2019ll provide a tutorial for creating a simple [&hellip;]<\/p>\n","protected":false},"author":12,"featured_media":159957,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[88,91],"tags":[191,192,131,135,190],"class_list":["post-2548","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tools","category-articles","tag-red-teaming","tag-sliver","tag-golang","tag-windows","tag-c2"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HN Security - Customizing Sliver - Part 3 -<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HN Security - Customizing Sliver - Part 3 -\" \/>\n<meta property=\"og:description\" content=\"In this third and final post in the series about Sliver C2 I\u2019ll provide a tutorial for creating a simple [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/\" \/>\n<meta property=\"og:site_name\" content=\"HN Security\" \/>\n<meta property=\"article:published_time\" content=\"2023-10-24T09:54:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-09-15T13:24:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/SILVER.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"836\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Alessandro Iandoli\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hnsec\" \/>\n<meta name=\"twitter:site\" content=\"@hnsec\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alessandro Iandoli\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/\"},\"author\":{\"name\":\"Alessandro Iandoli\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/person\\\/7883a9c36dac7694ca101137125d5fff\"},\"headline\":\"Customizing Sliver &#8211; Part 3\",\"datePublished\":\"2023-10-24T09:54:58+00:00\",\"dateModified\":\"2025-09-15T13:24:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/\"},\"wordCount\":2238,\"publisher\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/SILVER.jpg\",\"keywords\":[\"red teaming\",\"sliver\",\"golang\",\"windows\",\"c2\"],\"articleSection\":[\"Tools\",\"Articles\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/\",\"name\":\"HN Security - Customizing Sliver - Part 3 -\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/SILVER.jpg\",\"datePublished\":\"2023-10-24T09:54:58+00:00\",\"dateModified\":\"2025-09-15T13:24:23+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/SILVER.jpg\",\"contentUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2025\\\/09\\\/SILVER.jpg\",\"width\":1600,\"height\":836,\"caption\":\"Silver Framework logo\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/customizing-sliver-part-3\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Customizing Sliver &#8211; Part 3\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\",\"name\":\"HN Security\",\"description\":\"Offensive Security Specialists\",\"publisher\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#organization\",\"name\":\"HN Security\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/hn-libellula.jpg\",\"contentUrl\":\"https:\\\/\\\/hnsecurity.it\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/hn-libellula.jpg\",\"width\":696,\"height\":696,\"caption\":\"HN Security\"},\"image\":{\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/hnsec\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/hnsecurity\\\/\",\"https:\\\/\\\/github.com\\\/hnsecurity\",\"https:\\\/\\\/infosec.exchange\\\/@hnsec\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/#\\\/schema\\\/person\\\/7883a9c36dac7694ca101137125d5fff\",\"name\":\"Alessandro Iandoli\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g\",\"caption\":\"Alessandro Iandoli\"},\"url\":\"https:\\\/\\\/hnsecurity.it\\\/it\\\/blog\\\/author\\\/ale98\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HN Security - Customizing Sliver - Part 3 -","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/","og_locale":"it_IT","og_type":"article","og_title":"HN Security - Customizing Sliver - Part 3 -","og_description":"In this third and final post in the series about Sliver C2 I\u2019ll provide a tutorial for creating a simple [&hellip;]","og_url":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/","og_site_name":"HN Security","article_published_time":"2023-10-24T09:54:58+00:00","article_modified_time":"2025-09-15T13:24:23+00:00","og_image":[{"width":1600,"height":836,"url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/SILVER.jpg","type":"image\/jpeg"}],"author":"Alessandro Iandoli","twitter_card":"summary_large_image","twitter_creator":"@hnsec","twitter_site":"@hnsec","twitter_misc":{"Scritto da":"Alessandro Iandoli","Tempo di lettura stimato":"11 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/#article","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/"},"author":{"name":"Alessandro Iandoli","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/7883a9c36dac7694ca101137125d5fff"},"headline":"Customizing Sliver &#8211; Part 3","datePublished":"2023-10-24T09:54:58+00:00","dateModified":"2025-09-15T13:24:23+00:00","mainEntityOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/"},"wordCount":2238,"publisher":{"@id":"https:\/\/hnsecurity.it\/it\/#organization"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/SILVER.jpg","keywords":["red teaming","sliver","golang","windows","c2"],"articleSection":["Tools","Articles"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/","url":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/","name":"HN Security - Customizing Sliver - Part 3 -","isPartOf":{"@id":"https:\/\/hnsecurity.it\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/#primaryimage"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/SILVER.jpg","datePublished":"2023-10-24T09:54:58+00:00","dateModified":"2025-09-15T13:24:23+00:00","breadcrumb":{"@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/#primaryimage","url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/SILVER.jpg","contentUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/SILVER.jpg","width":1600,"height":836,"caption":"Silver Framework logo"},{"@type":"BreadcrumbList","@id":"https:\/\/hnsecurity.it\/it\/blog\/customizing-sliver-part-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hnsecurity.it\/it\/"},{"@type":"ListItem","position":2,"name":"Customizing Sliver &#8211; Part 3"}]},{"@type":"WebSite","@id":"https:\/\/hnsecurity.it\/it\/#website","url":"https:\/\/hnsecurity.it\/it\/","name":"HN Security","description":"Offensive Security Specialists","publisher":{"@id":"https:\/\/hnsecurity.it\/it\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hnsecurity.it\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Organization","@id":"https:\/\/hnsecurity.it\/it\/#organization","name":"HN Security","url":"https:\/\/hnsecurity.it\/it\/","logo":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/","url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg","contentUrl":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2026\/01\/hn-libellula.jpg","width":696,"height":696,"caption":"HN Security"},"image":{"@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/hnsec","https:\/\/www.linkedin.com\/company\/hnsecurity\/","https:\/\/github.com\/hnsecurity","https:\/\/infosec.exchange\/@hnsec"]},{"@type":"Person","@id":"https:\/\/hnsecurity.it\/it\/#\/schema\/person\/7883a9c36dac7694ca101137125d5fff","name":"Alessandro Iandoli","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/644822f5d8329ca419a50c1f39c97de5ccd163d1932e4cdc60a6cc8cb64ed29e?s=96&d=mm&r=g","caption":"Alessandro Iandoli"},"url":"https:\/\/hnsecurity.it\/it\/blog\/author\/ale98\/"}]}},"jetpack_featured_media_url":"https:\/\/hnsecurity.it\/wp-content\/uploads\/2025\/09\/SILVER.jpg","_links":{"self":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/2548","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/users\/12"}],"replies":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/comments?post=2548"}],"version-history":[{"count":1,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/2548\/revisions"}],"predecessor-version":[{"id":160123,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/posts\/2548\/revisions\/160123"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media\/159957"}],"wp:attachment":[{"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/media?parent=2548"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/categories?post=2548"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hnsecurity.it\/it\/wp-json\/wp\/v2\/tags?post=2548"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}