-
-
Save lpowell/8a7b0bbdd8c408a03b0d29911db6f052 to your computer and use it in GitHub Desktop.
This script extracts title information from an MP3 file and injects specified content into the field.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| MP3 Stuffing | |
| Use a titled (TIT2 frame) MP3 file. | |
| This script extracts title information from an MP3 file and injects specified content into the field. This content could be extracted and executed by malicious actors. Or anyone really. | |
| This is just a mock up, and I might make a more in-depth and actually good version later. | |
| #> | |
| # Get file bytes of MP3 | |
| $file_bytes = [System.IO.File]::ReadAllBytes("PATH\\TO\\MP3") | |
| # Find the TIT2 frame | |
| $hold = '' | |
| $i=0 | |
| foreach ($b in $file_bytes){ | |
| if($b -gt 32 -and $b -lt 126){ | |
| $hold += [char]$b | |
| } else { | |
| if ($hold -match 'TIT2'){ | |
| break | |
| } | |
| $hold = '' | |
| } | |
| $i++ | |
| } | |
| # Offset of title frame | |
| write-host "offset: $i" | |
| # Get size of title | |
| $size = $file_bytes[($i)..($i+3)] | |
| Write-Host "Current size: $size" | |
| # Get Content | |
| # Endianness | |
| [array]::Reverse($size) | |
| $content = $file_bytes[($i+6)..($i+6+[System.BitConverter]::ToInt32($size,0))] | |
| Write-Host "Content (bytes): $content" | |
| $content = [string]::new($content) | |
| Write-Host "Content: $content" | |
| # Inject content: | |
| # Get string | |
| $inject = Read-Host "Inject: " | |
| #Convert to bytes | |
| $inject = [System.Text.Encoding]::UTF8.GetBytes($inject) | |
| #Get Length | |
| $inject_length = [System.bitconverter]::GetBytes($inject.Length) | |
| [array]::reverse($inject_length) | |
| #clone original file | |
| $copy_bytes = $file_bytes.Clone() | |
| # Preserve header | |
| $header = $copy_bytes[0..($i-1)] | |
| # Preserve footer | |
| $footer = $copy_bytes[($i+6+[System.BitConverter]::ToInt32($size,0))..$copy_bytes.Length] | |
| # Account for flag bytes | |
| $flags = [System.Byte[]]::CreateInstance([System.Byte],2) | |
| # Write to new file | |
| [System.IO.File]::WriteAllBytes("outfile.mp3",[byte[]]$header+[byte[]]$inject_length+[byte[]]$flags +[byte[]]$inject+[byte[]]$footer) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Leaving some notes here as well. I want to come back to this at some point.
All ID3v2 frames consists of one frame header followed by one or more
fields containing the actual information. The header is always 10
bytes and laid out as follows:
The frame ID is followed by a size descriptor containing the size of
the data in the final frame, after encryption, compression and
unsynchronisation. The size is excluding the frame header ('total
frame size' - 10 bytes) and stored as a 32 bit synchsafe integer.
In the frame header the size descriptor is followed by two flag
bytes. These flags are described in section 4.1.
There is no fixed order of the frames' appearance in the tag,
although it is desired that the frames are arranged in order of
significance concerning the recognition of the file. An example of
such order: UFID, TIT2, MCDI, TRCK ...
A tag MUST contain at least one frame. A frame must be at least 1
byte big, excluding the header.
https://id3.org/id3v2.4.0-frames
https://id3.org/id3v2.4.0-structure
Header starts with:
49 44 33 04 00 00 00 00 20 27 54 53 53 45 00 00 00 0E 00 00 00 4C 61 76 66 35 37 2E 38 33 2E 31 30 30
Windows inserts frame immediately after header and before footer.
54 49 54 32 00 00 00 05 00 00 00 74 65 73 74
T I T 2 . . . . . . t e s t
(TIT2 is a title tag)
00 FF FB 50
Insert tag as:
|T E X T |00 00 00 | 00 00| 00 |
[1] TAG
[2] size lsb
[3] optional flags
[4] content