---
name: "authoscope"
section: "1"
platform: "linux"
package: "authoscope"
version: "0.9.0-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/authoscope"
---

# authoscope(1)

scriptable network authentication cracker

## NAME

authoscope - scriptable network authentication cracker

## SYNOPSIS

**authoscope** \[**-nVh**\] command

## DESCRIPTION

authoscope is a scriptable network authentication cracker. While the space for common service bruteforce is already very well saturated, you may still end up writing your own python scripts when testing credentials for web applications.

The scope of authoscope is specifically cracking custom services. This is done by writing scripts that are loaded into a lua runtime. Those scripts represent a single service and provide a \`verify(user, password)\` function that returns either true or false. Concurrency, progress indication and reporting is magically provided by the authoscope runtime.

## OPTIONS

- **-n**, **--workers** \<workers\>

  The number of concurrent workers to run.

- **-o**, **--output** \<output\>

  Write results to this file.

- **-v**, **--verbose**

  Enable verbose output.

- **-h**, **--help**

  Prints help information.

- **-V**, **--version**

  Prints version information.

## SUBCOMMANDS

Pick one of the following subcommands.

### Dictionary attack

Try each password for each user with every script.

**authoscope dict** \<**users**\> \<**passwords**\> \[**scripts**\]...

### Credential confirmation

Load a list of credentials with the format **user:password** and verify them with every script.

**authoscope creds** \<**credentials**\> \[**scripts**\]...

### Username enumeration

Takes a list of username and verifies they exist on the system. This is still executing the **verify** function with two arguments, but the password is set to **nil**. You may write a script that can do both by checking the password for nil to detect in which mode the script is executed.

**authoscope enum** \<**users**\> \[**scripts**\]...

### Oneshot

Test a single username-password combination using a specific script. This command is also useful when developing a new script. If the password argument is omitted, the script is executed in enumerate mode. If you want to use this command in scripts, set -x so the exitcode is set to 2 if the credentials are invalid.

**authoscope oneshot** \[**-x**\] \<**script**\> \<**user**\> \[**password**\]

## RUNTIME REFERENCE

The authoscope runtime provides a number of functions that can be used to test target systems.

### base64\_decode

Decode a base64 string.

```
base64_decode("ww==")
```

### base64\_encode

Encode a binary array with base64.

```
base64_encode("\x00\xff")
```

### clear\_err

Clear all recorded errors to prevent a requeue.

```
if last_err() then
    clear_err()
    return false
else
    return true
end
```

### execve

Execute an external program. Returns the exit code.

```
execve("myprog", {"arg1", "arg2", "--arg", "3"})
```

### hex

Hex encode a list of bytes.

```
hex({0x6F, 0x68, 0x61, 0x69, 0x0A, 0x00})
```

### hmac\_md5

Calculate an hmac with md5. Returns a binary array.

```
hmac_md5("secret", "my authenticated message")
```

### hmac\_sha1

Calculate an hmac with sha1. Returns a binary array.

```
hmac_sha1("secret", "my authenticated message")
```

### hmac\_sha2\_256

Calculate an hmac with sha2\_256. Returns a binary array.

```
hmac_sha2_256("secret", "my authenticated message")
```

### hmac\_sha2\_512

Calculate an hmac with sha2\_512. Returns a binary array.

```
hmac_sha2_512("secret", "my authenticated message")
```

### hmac\_sha3\_256

Calculate an hmac with sha3\_256. Returns a binary array.

```
hmac_sha3_256("secret", "my authenticated message")
```

### hmac\_sha3\_512

Calculate an hmac with sha3\_512. Returns a binary array.

```
hmac_sha3_512("secret", "my authenticated message")
```

### html\_select

Parses an html document and returns the first element that matches the css selector. The return value is a table with **text** being the inner text and **attrs** being a table of the elements attributes.

```
csrf = html_select(html, 'input[name="csrf"]')
token = csrf["attrs"]["value"]
```

### html\_select\_list

Same as **html\_select** but returns all matches instead of the first one.

```
html_select_list(html, 'input[name="csrf"]')
```

### http\_basic\_auth

Sends a **GET** request with basic auth. Returns **true** if no **WWW-Authenticate** header is set and the status code is not **401**.

```
http_basic_auth("https://httpbin.org/basic-auth/foo/buzz", user, password)
```

### http\_mksession

Create a session object. This is similar to **requests.Session** in python-requests and keeps track of cookies.

```
session = http_mksession()
```

### http\_request

Prepares an http request. The first argument is the session reference and cookies from that session are copied into the request. After the request has been sent, the cookies from the response are copied back into the session.

The next arguments are the **method**, the **url** and additional options. Please note that you still need to specify an empty table **{}** even if no options are set. The following options are available:

```
- query - a map of query parameters that should be set on the url
- headers - a map of headers that should be set
- basic_auth - configure the basic auth header with {"user, "password"}
- user_agent - overwrite the default user agent with a string
- json - the request body that should be json encoded
- form - the request body that should be form encoded
- body - the raw request body as string
```

```
req = http_request(session, 'POST', 'https://httpbin.org/post', {
    json={
        user=user,
        password=password,
    }
})
resp = http_send(req)
if last_err() then return end
if resp["status"] ~= 200 then return "invalid status code" end
```

### http\_send

Send the request that has been built with **http\_request**. Returns a table with the following keys:

```
- status - the http status code
- headers - a table of headers
- text - the response body as string
```

```
req = http_request(session, 'POST', 'https://httpbin.org/post', {
    json={
        user=user,
        password=password,
    }
})
resp = http_send(req)
if last_err() then return end
if resp["status"] ~= 200 then return "invalid status code" end
```

### json\_decode

Decode a lua value from a json string.

```
json_decode("{\"data\":{\"password\":\"fizz\",\"user\":\"bar\"},\"list\":[1,3,3,7]}")
```

### json\_encode

Encode a lua value to a json string. Note that empty tables are encoded to an empty object **{}** instead of an empty list **\[\]**.

```
x = json_encode({
    hello="world",
    almost_one=0.9999,
    list={1,3,3,7},
    data={
        user=user,
        password=password,
        empty=nil
    }
})
```

### last\_err

Returns **nil** if no error has been recorded, returns a string otherwise.

```
if last_err() then return end
```

### ldap\_bind

Connect to an ldap server and try to authenticate with the given user

```
ldap_bind("ldaps://ldap.example.com/",
    "cn=\"" .. ldap_escape(user) .. "\",ou=users,dc=example,dc=com", password)
```

### ldap\_escape

Escape an attribute value in a relative distinguished name.

```
ldap_escape(user)
```

### ldap\_search\_bind

Connect to an ldap server, log into a search user, search for the target user and then try to authenticate with the first DN that was returned by the search.

```
ldap_search_bind("ldaps://ldap.example.com/",
    -- the user we use to find the correct DN
    "cn=search_user,ou=users,dc=example,dc=com", "searchpw",
    -- base DN we search in
    "dc=example,dc=com",
    -- the user we test
    user, password)
```

### md5

Hash a byte array with md5 and return the results as bytes.

```
hex(md5("\x00\xff"))
```

### mysql\_connect

Connect to a mysql database and try to authenticate with the provided credentials. Returns a mysql connection on success.

```
sock = mysql_connect("127.0.0.1", 3306, user, password)
```

### mysql\_query

Run a query on a mysql connection. The 3rd parameter is for prepared statements.

```
rows = mysql_query(sock, 'SELECT VERSION(), :foo as foo', {
    foo='magic'
})
```

### print

Prints the value of a variable. Please note that this bypasses the regular writer and may interfer with the progress bar. Only use this for debugging.

```
print({
    data={
        user=user,
        password=password
    }
})
```

### rand

Returns a random **u32** with a minimum and maximum constraint. The return value can be greater or equal to the minimum boundary, and always lower than the maximum boundary. This function has not been reviewed for cryptographic security.

```
rand(0, 256)
```

### randombytes

Generate the specified number of random bytes.

```
randombytes(16)
```

### sha1

Hash a byte array with sha1 and return the results as bytes.

```
hex(sha1("\x00\xff"))
```

### sha2\_256

Hash a byte array with sha2\_256 and return the results as bytes.

```
hex(sha2_256("\x00\xff"))
```

### sha2\_512

Hash a byte array with sha2\_512 and return the results as bytes.

```
hex(sha2_512("\x00\xff"))
```

### sha3\_256

Hash a byte array with sha3\_256 and return the results as bytes.

```
hex(sha3_256("\x00\xff"))
```

### sha3\_512

Hash a byte array with sha3\_512 and return the results as bytes.

```
hex(sha3_512("\x00\xff"))
```

### sleep

Pauses the thread for the specified number of seconds. This is mostly used to debug concurrency.

```
sleep(3)
```

### sock\_connect

Create a tcp connection.

```
sock = sock_connect("127.0.0.1", 1337)
```

### sock\_send

Send data to the socket.

```
sock_send(sock, "hello world")
```

### sock\_recv

Receive up to 4096 bytes from the socket.

```
x = sock_recv(sock)
```

### sock\_sendline

Send a string to the socket. A newline is automatically appended to the string.

```
sock_sendline(sock, line)
```

### sock\_recvline

Receive a line from the socket. The line includes the newline.

```
x = sock_recvline(sock)
```

### sock\_recvall

Receive all data from the socket until EOF.

```
x = sock_recvall(sock)
```

### sock\_recvline\_contains

Receive lines from the server until a line contains the needle, then return this line.

```
x = sock_recvline_contains(sock, needle)
```

### sock\_recvline\_regex

Receive lines from the server until a line matches the regex, then return this line.

```
x = sock_recvline_regex(sock, "^250 ")
```

### sock\_recvn

Receive exactly n bytes from the socket.

```
x = sock_recvn(sock, 4)
```

### sock\_recvuntil

Receive until the needle is found, then return all data including the needle.

```
x = sock_recvuntil(sock, needle)
```

### sock\_sendafter

Receive until the needle is found, then write data to the socket.

```
sock_sendafter(sock, needle, data)
```

### sock\_newline

Overwrite the default \`\\n\` newline.

```
sock_newline(sock, "\r\n")
```

## SECURITY

To report a security issue please contact kpcyrd on ircs://irc.hackint.org.

## SEE ALSO

The documentation at lua.org.

## AUTHORS

This program was originally written and is currently maintained by kpcyrd. Bugs and patches are welcome on github:

*https://github.com/kpcyrd/authoscope*
