skip to content

In Wireshark, how do you prove from a capture taken next to the client whether a downloaded file that arrives corrupted was already wrong on the wire?

level: seniorimportance: should knowfreq 12%

answer

  1. the capture point is the reference
  2. completeness before comparison
  3. missing-bytes marker, contiguity count
  4. hash the export against both copies
  5. bracket with a second capture

basics

~20 s

Prove the capture holds the whole stream (no missing-bytes marker in Follow TCP Stream, contiguity count 1), then hash the exported object against the server and client copies; the pair that matches places the change before or after the capture point.

solid answer

~50 s

A capture proves only what reached the capture point, so start with completeness. Find the download's `tcp.stream`, check Follow TCP Stream for `[N bytes missing in capture file]`, and check that `tcp.stream.server.contiguity_count` is 1 and `tcp.completeness` shows the handshake, data and close. A gap is a capture fact: it makes the export unusable as evidence, not proof of a network fault. Then save the body with **File > Export Objects > HTTP** and hash it. If it matches the server's file but not the client's, the bytes were right when they passed the capture point and the damage happened later, in client software, a local agent or the disk. If it differs from the server's file, the change happened before the capture point; take a second capture beside the server and compare the same object. Remember that Wireshark saves bodies dechunked and decompressed.

go deeper

for a junior

Recall that a capture shows only what reached the point where it was taken, and that Export Objects can save a downloaded file for comparison.

for a middle

Explain which signals show the stream is complete, and why the export is the decoded body rather than the wire bytes.

for a senior

Lead with completeness, compare hashes from the export, server and client, state each conclusion relative to the capture point, and know when a second capture is needed.

for a principal

Weigh where standing capture points belong so corruption disputes between teams or vendors can be settled from evidence rather than argument.

## What a capture can and cannot prove A capture records what arrived at **the capture point**: the interface, tap or host where the packets were copied. It says nothing directly about what happened before that point or after it. For a download that arrives corrupted, that is exactly the property you want: a capture next to the client can split the path into "before here" and "after here", but only if it holds every byte of the transfer. The method is to establish completeness first, extract the body, and then compare hashes. ## Step 1: prove the stream is complete 1. Find the download, for example with `http.request` and the URI, and note its `tcp.stream` index. If the client retried from the same source port, each attempt has its own index; pick the one that produced the corrupted file. 2. Open **Follow TCP Stream** and search the server's data for a `[N bytes missing in capture file]` marker. 3. Read the stream fields in the packet details. The contiguity counts come from TCP sequence analysis, which is on by default. | Signal | Where you see it | What it means for the export | |---|---|---| | `[N bytes missing in capture file]` | Follow TCP Stream | The client acknowledged bytes the capture lacks; the export is incomplete | | `tcp.stream.server.contiguity_count` other than 1 | Packet details of the stream | 0 means no server data captured, 2 or more means gaps | | `tcp.completeness` without the data and close bits | Packet details of the stream | The capture started late or stopped early | | HTTP body shown as Continuation | Packet list | The body could not be reassembled from what was captured | Every one of these is a statement about the **capture**. A gap the client acknowledged was delivered to the client; it does not show the network damaged anything. How the analyser flags lost and retransmitted segments is a separate subject. ## Step 2: extract the bytes the client received - **File > Export Objects > HTTP** saves the **entity body** as the client application received it: chunked transfer coding removed and, with **Uncompress entity bodies** on, gzip, deflate or brotli encoding undone. Compare it with the server's original file. - **Follow TCP Stream**, shown as **Raw** and saved with **Save as...**, gives the literal payload of one direction, headers included. Use it when the encoding itself is in question. - Over HTTPS, neither view shows the body until Wireshark can decrypt the session with its key material. ## Step 3: compare and localise Hash the export, the server's file and the client's corrupted copy: | Export vs server | Export vs client | Conclusion | |---|---|---| | Match | Differ | Bytes were intact at the capture point; the change happened after it, on the client side | | Differ | Match | The client stored what it received; the change happened before the capture point | | Differ | Differ | Check completeness and encoding again, then capture at a second point | ## Bracketing with a second capture When the change happened before the client's capture point, capture the same download beside the server, export the object again and compare. Two complete captures with different exports put the change between them: a proxy, a filtering gateway or a device that rewrites content. How the packets reach each capture point is a port-mirroring and tap subject; the analyser's job is to compare like with like. ## Traps that produce false verdicts - **Trusting the checksum column.** Wireshark's TCP checksum validation is off by default, and on the capturing host offloaded checksums can look wrong. Neither state proves the payload intact or damaged. - **Comparing different encodings.** A decoded export compared with a compressed copy, or the other way round, always differs. - **Comparing the wrong attempt.** Retries on a recycled source port are separate streams; hash the attempt the client actually kept. - **An overloaded capture host.** A capture that dropped packets cannot support either verdict; repeat it with a capture setup that keeps up. - **Forgetting where the capture point was.** A capture taken on the client host sits inside that machine, after its network card but before the application; a capture from the network sits before both. Name the capture point in every conclusion you write down.

  • Why hash the Export Objects file rather than the Raw bytes saved from Follow TCP Stream?
    The server stores a file, not an HTTP response. The Raw view of the server's direction holds the response headers and any chunked framing or content encoding, so its hash never equals the stored file. Export Objects saves the decoded entity body, which is what the client application wrote. Use the Raw bytes only when the encoding itself is in question.
  • The export differs from the server's file, but the client stored exactly what the export shows. What next?
    The change happened before the client's capture point. Capture the same download beside the server and export it again. If that export matches the server file, something between the two capture points rewrote the content; if it already differs, look at the server side, its software or anything in front of it.

saying these in an interview costs you the question

  • A gap in the captured stream proves the network corrupted the download.
  • If the Wireshark export differs from the server's file, the network path is to blame.
  • A clean TCP checksum column proves the payload arrived intact.
  • One capture anywhere on the path is enough to blame a specific hop.
  • Export Objects saves the raw wire bytes, so it must equal the compressed transfer.