Scan samples via DeepMalware

DeepBits Malware Analysis API

The DeepBits Malware Analysis API provides a set of endpoints to analyze and identify unknown malware variants using code reuse. It uses the DeepDi disassembler to quickly generate disassembly code and compares it with other known malware samples to detect and identify the malware family.

You can check the detail by the malware api specification doc.

Usage guide

This guide describes the overall process of using the DeepBits Malware Analysis API to analyze and detect malware variants using code reuse.

Upload Malware File

First, you need to get a presigned S3 request by making a POST request to /malware/upload_url. This will return an S3 bucket URL and a S3 path for the malware sample that you will use in subsequent requests.

Then, you can use the returned S3 bucket URL to upload the malware file to an S3 bucket. Sample curl as below:

curl --location --request PUT 'https://presigned-url' \
--header 'Content-Type: application/octet-stream' \
--data 'your binary file'

Once the upload is complete, you need to notify DeepBits by making a POST request to /malware/upload_success endpoint with the S3 blob path. This will trigger the analysis process for the uploaded malware file.

Get File Scan Result

To get the scan results of a submitted malware sample, you can make a GET request to /malware/hash/:sha or /malware/detail/:id, where :sha is the SHA256 hash value of the malware sample or :id is the unique ID returned from the /malware/upload_success API call.

Python sample for get upload URL and upload to S3 then notify deepbits upload success

import requests
import hashlib
import os

api_key = os.environ['API_KEY']

# read binary file from "./uploads/target.apk"
with open("./uploads/target.apk", "rb") as f:
    file_contents = f.read()

# send post request to https://api.deepbits.com/malware/upload_url with the filename read from #0.
upload_url_response = requests.post(
    "https://api.deepbits.com/malware/upload_url",
    json={"fileName": "target.apk"},
    headers={"x-api-key": api_key}
)

# extract S3 presigned put url from upload_url api response
put_url = upload_url_response.json()['data']['uploadUrl']

headers = {
	"Content-Type": "application/octet-stream",
	"x-api-key": api_key, 
	}

response = requests.put(
    put_url,
    data=file_contents,
    headers=headers
)

# call PUT https://api.deepbits.com/malware/upload_success with JSON body
upload_success_response = requests.put(
    "https://api.deepbits.com/malware/upload_success",
    json={
        "path": upload_url_response.json()['data']['path'],
        "hash": hashlib.sha256(file_contents).hexdigest(),
        "fileName": "target.apk"
    },
    headers={"x-api-key": api_key}
)

# print the response from upload_success api
print(upload_success_response.content)

env API_KEY="your api key" python3 ./main.py

The response will contain information about the malware sample, including its hash value, family name, and other relevant details. You can also view the list of functions in the sample and their occurrence counts by /malware/detail/:id/functions API once scan status change to Completed.

Know the scan status

Once the /malware/upload_success get called, we'll start to scan the sample you uploaded. You can get the scan status via these two API.

GET https://api.deepbits.com/malware/detail/{id}, or

GET https://api.deepbits.com/malware/hash/{sha}

In the response of these two API, there will be a status field, the status field can be:

status {
	NotScanned = 'NotScanned',
	Scanning = 'Scanning',
	Failed = 'Failed',
	Completed = 'Completed',
}

Once your scan status become Completed you can call further APIs like get function detail. You can use polling to call this API, and it is recommended to call it every two minutes.

Get Function Details

To get the details of a specific function in the submitted malware sample, you can call the GET /malware/detail/:id/functions/:address/:sha256 API endpoint, where :id is the unique ID returned from the PUT /malware/upload_success API call, :address is the address of the function, and :sha256 is the SHA256 hash value of the sample.

The response will contain the disassembly code of the requested function and a list of similar functions in other known malware samples.

Compare Functions

To compare the disassembly code of a function in the submitted sample with a similar function in another known malware sample, you can call the /malware/detail/:id/functions/:address/:sha256/compare API endpoint, for specific URL params you can check our API specific docs.

The response will contain the comparison result between the two disassembled functions.

Conclusion

By following these steps, you can easily upload and analyze malware samples using the DeepBits Malware Analysis API. You can also get detailed information about specific functions and compare them with other known malware samples to better understand their behavior and identify their malware family.

Notes

This guide will show you how to generate your API KEY.

Python Demo Code

import requests
import hashlib
import os
import time

# Update these two
FILE_TO_UPLOAD = '' 
API_KEY = ''

API_BASE = 'https://api.deepbits.com'

default_headers = {"x-api-key": API_KEY}

def upload_file(file_path, api_key):
    with open(file_path, "rb") as f:
        file_contents = f.read()

    print(f"Get upload URL for {os.path.basename(file_path)}...")
    file_name = os.path.basename(file_path)
    upload_url_response = requests.post(
        f"{API_BASE}/malware/upload_url",
        json={"fileName": file_name},
        headers=default_headers
    )

    if (upload_url_response.json()['meta']['code'] == 403):
        print("API key is invalid")
        raise Exception("API key is invalid")

    put_url = upload_url_response.json()['data']['uploadUrl']

    headers = {
        "Content-Type": "application/octet-stream",
        "x-api-key": api_key, 
        }

    print(f"Upload {os.path.basename(file_path)} to S3...")
    response = requests.put(
        put_url,
        data=file_contents,
        headers=headers
    )

    print(f"Trigger upload_success...")
    upload_success_response = requests.put(
        f"{API_BASE}/malware/upload_success",
        json={
            "path": upload_url_response.json()['data']['path'],
            "hash": hashlib.sha256(file_contents).hexdigest(),
            "fileName": os.path.basename(file_path)
        },
        headers=default_headers
    )

    print(f"Upload Success Response: {upload_success_response.json()}\n")
    return upload_success_response.json()

def check_status(detail_id):
    max_retries = 50
    retry_interval = 10  # in seconds

    for i in range(max_retries):
        response = requests.get(
            f"{API_BASE}/malware/detail/{detail_id}",
            headers=default_headers,
        )

        status = response.json()["data"]["status"]

        if status == "Completed":
            print("Scan Status: Completed")
            return response.json()
        else:
            print(f"Current Status: {status}")
            print(f"Retrying in {retry_interval} seconds...")
            time.sleep(retry_interval)
    else:
        raise ValueError("Max retries exceeded. API call failed.")

def get_functions(detail_id, sortBy, page, size):
    response = requests.get(
        f"{API_BASE}/malware/detail/{detail_id}/functions?sortBy={sortBy}&page={page}&size={size}",
        headers=default_headers,
    )

    return response.json()

def get_function(detail_id, address, sha256):
    response = requests.get(
        f"{API_BASE}/malware/detail/{detail_id}/functions/{address}/{sha256}",
        headers=default_headers,
    )

    return response.json()


# upload file
upload_res = upload_file(FILE_TO_UPLOAD, API_KEY)
detail_id = upload_res['data']['_id']

# check scan status
detail_res = check_status(detail_id)
if detail_res['data'].get('failure'):
    print(f"Scan failed with error: {detail_res['data']['failure']} \n")
    raise Exception("Scan failed due to file not support")
else:
  scan_result = requests.get(
    f"{API_BASE}/malware/detail/{detail_id}",
    headers=default_headers
  )
  print(f"Scan success with scan_result: \n{scan_result.json()} \n")

# get functions once scan is completed
functions_res = get_functions(detail_id, 'relevance', 1, 10);

functions_count = functions_res['data']['total_function_count']
print(f"Total functions: {functions_count} \n")

# get first function detail
first_function = functions_res['data']['functions'][0]
first_function_detail = get_function(detail_id, first_function[1], first_function[0])
print(f"First function: \n{first_function_detail} \n")

print("Demo run successfully without error, get API docs on https://docs.deepbits.com/reference/get_malware-detail-id")