First a bit of background on the subject:
Tempest is the concept of being able to retrieve usable information about what data is being processed by a computer or other electronic device, entirely from the "electronic noise" that is given off by that device. These RF emissions usually cause trouble if they cause interference with radio receivers like an AM radio that you are trying to listen to. The FCC has standards for reducing this interference to an acceptable level, but even so, if you are TRYING to pick up this signal it is usually possible.
Screen:
Under the right conditions, this interference isn't just unintelligible noise, but can actually convey data that is being processed by the computer at that time. This can cause a privacy risk if the data being processed that causes these RF emissions contains information is confidential. This could be the case if for example you are looking at a document on your PC that has confidential information, but your monitor's RF emissions allow the screen image to be received by an adversary with a radio receiver.
To demonstrate the ability of a monitor to transmit intelligible information, Erik Thiele created a program called "Tempest for Eliza" (which you can read about here http://www.erikyyy.de/tempest/) which transmits Beethoven's song Fur Elise. It depends on the ability of a CRT monitor to send one pixel at a time to the screen with an electron gun, so that the signal going to the electron gun gets radiated as RF. So to send a tone, the brightness of a pixel is based on both the frequency of the audible tone and the RF frequency that you want to have to tune your AM radio to to receive it.
Unfortunately, this program has several problems. One is that it requires being compiled (no binaries can be downloaded). Another is that it only runs on Linux. And lastly, it is based on a CRT monitor which sends one pixel at a time. The last of these is a problem because modern LCD monitors process data one line at a time. While vertically, each line of the display is set in sequence, within each line, all of the pixels are set simultaneously. There is no "pixel clock" in an LCD monitor, just a line clock and a data clock. The data clock runs very fast like a CPU processor (probably at 10s or 100s of megahertz at least) and handles the image data very fast for that particular line. Depending on the monitor's microcontroller clock speed (which can be pretty much anything, and not predictable like the pixel clock of a CRT monitor), you will have the carrierwave signal based on that clock speed. Depending on what that frequency is, you may need to tune around your radio to find it or one of its harmonics (sometimes these can be lower than the clock frequency in the form of a lower side band). There's not much than can be done about this, except tune your AM radio (preferably a shortwave receiver so you get more frequencies to search through) to the strongest signal for your particular LCD monitor. However, since you don't need to worry about the pixels horizontally, that means that every pixel on a given line can be lit up at maximum brightness, and I have found that this actually makes the signal stronger. You only need to worry about modulating the brightness vertically.
And here's the solution I've found:
Of course, there's a pretty simple solution to fixing these things at once. To fix the first 2 things, just write your own version of this software in a language you are familiar with and which is designed to compile for Windows (VB6 in this case). And the last thing is to make it so that every pixel is lit up on a given line, which naturally is easy to do when you are writing it yourself (you just write it to do that). So below, there are 2 links to my VB6 version of this guy's program, designed from the ground up to work with LCD monitors (sorry if you want to use it with a CRT monitor, it won't work, as I've made this based on the fact that nearly everyone uses LCD not CRT monitors nowadays). The first link fixes problem 2 and 3 (it is made for Windows, not Linux, and it is optimized for LCD screens, but still requires compiling). The second link fixes all 3 problems. It has the source code, just as with the first link, but it also has a compiled EXE file (in case you don't want to go through the hassle of compiling it yourself, or if you don't have a copy of VB6 yourself). If you are really paranoid about viruses and stuff, you can use the first link, but as it is not a virus (I have no desire to hack anybody's PC) I would highly recommend the second link, which has all the source code (just as with the first link) and also has the compiled EXE file.
The name of the program is "Tempest Test for Windows". With it, you can determine how much RF signal is coming from your monitor that actually conveys information about what's on your computer screen, with the idea that if you are running a business that has confidential info on your computer, and you find that you can hear the music from this program playing on a nearby radio, you should consider Faraday shielding your PC or the room that the PC is in. As with the original "Tempest for Eliza" (which was created by Erik Thiele), it plays Fur Elise. The notes data are in the "song.txt" file, which can be edited to make it play any musical piece that you want.
Source code only: http://www.mediafire.com/?8f21lgj8bw6ed63
Source code and EXE: http://www.mediafire.com/?1mlhl1ir8j7fm2n
Controls:
There's only one control, the Esc key. Press it to close the program before the song has finished playing. If the song is allowed to continue playing, the program will close when the song ends.
Format of the "song.txt" file:
It is case-insensitive. Each note is specified by note letter, a modifier symbol ("#" for sharp, or "b" for flat, and yes that is a lowercase "B", but uppercase works as well, as the program is completely case insensitive), and an octave number (from 0 to 8), in that order. In the case of it not being sharp or flat, you leave out the modifier. For example, D sharp in octave 4 is D#4 (or d#4), while B normal in octave 7 is B7 (or b7), and B flat in octave 2 is Bb2 (or bb2, or bB2, or BB2). Each note or special symbol is separated from each other by a space. There are 2 special symbols ("." and "-"). The "." represents no tone transmitted for the period of one half of a note. The dash represents holding the previous note for a period of one note. Any other text in a given entry, or a blank entry (such as formed by an extra space at the start or end of the text file, or by 2 consecutive spaces in the middle of the file) will trigger the error "Stop statement encountered". This is because I left a stop statement in it while debugging it, prior to compiling it. That stopped the code is designed to stop it so that you can check one of the variables that holds the string for that note or special symbol, to see why it didn't match what the program was expecting (so you could go search for the specific bad string in the song.txt file and correct it). It's not nearly as useful with the EXE file, as it alerts you to the fact that there is something wrong with the file, but you'll need to manually look through the text file to see what's wrong. But I left it in anyway so that you could see if there is in fact something wrong with the text file, should you decide to edit it and put in your own song.
Code:
Private Declare Sub FillMemory Lib "kernel32.dll" Alias "RtlFillMemory" (ByRef Destination As Any, ByVal Length As Long, ByVal Fill As Byte) Private Declare Function SetDIBits Lib "gdi32.dll" (ByVal hDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, ByRef lpBits As Any, ByRef lpBI As BITMAPINFO, ByVal wUsage As Long) As Long Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long) Private Declare Function SetWindowPos Lib "user32.dll" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long Private Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As Long) As Integer Private Type BITMAPINFOHEADER biSize As Long biWidth As Long biHeight As Long biPlanes As Integer biBitCount As Integer biCompression As Long biSizeImage As Long biXPelsPerMeter As Long biYPelsPerMeter As Long biClrUsed As Long biClrImportant As Long End Type Private Type RGBQUAD rgbBlue As Byte rgbGreen As Byte rgbRed As Byte rgbReserved As Byte End Type Private Type BITMAPINFO bmiHeader As BITMAPINFOHEADER bmiColors(255) As RGBQUAD End Type Dim PicW As Long Dim PicH As Long Dim Pix() As Byte Dim BMI As BITMAPINFO Private Type Note Freqency As Single Duration As Long End Type Dim Song() As Note Dim ProgQuit As Boolean Private Sub Form_Activate() Dim y As Long Dim n As Long Dim z As Byte Dim Freq As Single Dim FrameRate As Long Dim FrameDuration As Single Dim LineDuration As Single Dim LineRate As Single FrameRate = 60 FrameDuration = 1 / FrameRate LineDuration = FrameDuration / PicH LineRate = 1 / LineDuration SetWindowPos Me.hWnd, -1, 0, 0, 0, 0, &H201 For n = 0 To UBound(Song) Freq = Song(n).Freqency For y = 0 To PicH - 1 FillMemory Pix(0, y), PicW, Sgn(Sin(2 * 3.14159 * Freq * y / LineRate)) * 127.5 + 127.5 Next y SetDIBits Me.hDC, Me.Image.Handle, 0, PicH, Pix(0, 0), BMI, 0 Refresh Sleep Song(n).Duration DoEvents If ProgQuit Then Exit Sub Next n Unload Me End Sub Private Sub Form_Load() Dim i As Long Dim NotesStr As String ChDir App.Path PicW = Screen.Width / 15 PicH = Screen.Height / 15 ReDim Pix(PicW - 1, PicH - 1) With BMI With .bmiHeader .biSize = 40 .biPlanes = 1 .biBitCount = 8 .biClrUsed = 256 .biClrImportant = 256 .biWidth = PicW .biHeight = -PicH End With For i = 0 To 255 With .bmiColors(i) .rgbRed = i .rgbGreen = i .rgbBlue = i End With Next i End With Open "song.txt" For Binary Access Read As #1 NotesStr = String$(LOF(1), vbNullChar) Get #1, 1, NotesStr Close #1 Song() = String2Notes(NotesStr, 300) GetAsyncKeyState vbKeyEscape Timer1.Enabled = True End Sub Private Function String2Notes(ByVal NotesStr As String, ByVal Duration As Long) As Note() Dim NoteStrings() As String Dim Notes() As Note Dim n As Long NoteStrings() = Split(NotesStr, " ") ReDim Notes(UBound(NoteStrings)) For n = 0 To UBound(Notes) With Notes(n) Select Case NoteStrings(n) Case "." .Freqency = 0 .Duration = Duration / 2 Case "-" .Freqency = Notes(n - 1).Freqency .Duration = Duration Case Else .Freqency = Note2Freq(NoteStrings(n)) .Duration = Duration End Select End With Next n String2Notes = Notes() End Function Private Function Note2Freq(ByVal NoteName As String) As Single Select Case LCase$(NoteName) Case "c0" Note2Freq = 16.35 Case "c#0", "db0" Note2Freq = 17.32 Case "d0" Note2Freq = 18.35 Case "d#0", "eb0" Note2Freq = 19.45 Case "e0" Note2Freq = 20.6 Case "f0" Note2Freq = 21.83 Case "f#0", "gb0" Note2Freq = 23.12 Case "g0" Note2Freq = 24.5 Case "g#0", "ab0" Note2Freq = 25.96 Case "a0" Note2Freq = 27.5 Case "a#0", "bb0" Note2Freq = 29.14 Case "b0" Note2Freq = 30.87 Case "c1" Note2Freq = 32.7 Case "c#1", "db1" Note2Freq = 34.65 Case "d1" Note2Freq = 36.71 Case "d#1", "eb1" Note2Freq = 38.89 Case "e1" Note2Freq = 41.2 Case "f1" Note2Freq = 43.65 Case "f#1", "gb1" Note2Freq = 46.25 Case "g1" Note2Freq = 49 Case "g#1", "ab1" Note2Freq = 51.91 Case "a1" Note2Freq = 55 Case "a#1", "bb1" Note2Freq = 58.27 Case "b1" Note2Freq = 61.74 Case "c2" Note2Freq = 65.41 Case "c#2", "db2" Note2Freq = 69.3 Case "d2" Note2Freq = 73.42 Case "d#2", "eb2" Note2Freq = 77.78 Case "e2" Note2Freq = 82.41 Case "f2" Note2Freq = 87.31 Case "f#2", "gb2" Note2Freq = 92.5 Case "g2" Note2Freq = 98 Case "g#2", "ab2" Note2Freq = 103.83 Case "a2" Note2Freq = 110 Case "a#2", "bb2" Note2Freq = 116.54 Case "b2" Note2Freq = 123.47 Case "c3" Note2Freq = 130.81 Case "c#3", "db3" Note2Freq = 138.59 Case "d3" Note2Freq = 146.83 Case "d#3", "eb3" Note2Freq = 155.56 Case "e3" Note2Freq = 164.81 Case "f3" Note2Freq = 174.61 Case "f#3", "gb3" Note2Freq = 185 Case "g3" Note2Freq = 196 Case "g#3", "ab3" Note2Freq = 207.65 Case "a3" Note2Freq = 220 Case "a#3", "bb3" Note2Freq = 233.08 Case "b3" Note2Freq = 246.94 Case "c4" Note2Freq = 261.63 Case "c#4", "db4" Note2Freq = 277.18 Case "d4" Note2Freq = 293.66 Case "d#4", "eb4" Note2Freq = 311.13 Case "e4" Note2Freq = 329.63 Case "f4" Note2Freq = 349.23 Case "f#4", "gb4" Note2Freq = 369.99 Case "g4" Note2Freq = 392 Case "g#4", "ab4" Note2Freq = 415.3 Case "a4" Note2Freq = 440 Case "a#4", "bb4" Note2Freq = 466.16 Case "b4" Note2Freq = 493.88 Case "c5" Note2Freq = 523.25 Case "c#5", "db5" Note2Freq = 554.37 Case "d5" Note2Freq = 587.33 Case "d#5", "eb5" Note2Freq = 622.25 Case "e5" Note2Freq = 659.25 Case "f5" Note2Freq = 698.46 Case "f#5", "gb5" Note2Freq = 739.99 Case "g5" Note2Freq = 783.99 Case "g#5", "ab5" Note2Freq = 830.61 Case "a5" Note2Freq = 880 Case "a#5", "bb5" Note2Freq = 932.33 Case "b5" Note2Freq = 987.77 Case "c6" Note2Freq = 1046.5 Case "c#6", "db6" Note2Freq = 1108.73 Case "d6" Note2Freq = 1174.66 Case "d#6", "eb6" Note2Freq = 1244.51 Case "e6" Note2Freq = 1318.51 Case "f6" Note2Freq = 1396.91 Case "f#6", "gb6" Note2Freq = 1479.98 Case "g6" Note2Freq = 1567.98 Case "g#6", "ab6" Note2Freq = 1661.22 Case "a6" Note2Freq = 1760 Case "a#6", "bb6" Note2Freq = 1864.66 Case "b6" Note2Freq = 1975.53 Case "c7" Note2Freq = 2093 Case "c#7", "db7" Note2Freq = 2217.46 Case "d7" Note2Freq = 2349.32 Case "d#7", "eb7" Note2Freq = 2489.02 Case "e7" Note2Freq = 2637.02 Case "f7" Note2Freq = 2793.83 Case "f#7", "gb7" Note2Freq = 2959.96 Case "g7" Note2Freq = 3135.96 Case "g#7", "ab7" Note2Freq = 3322.44 Case "a7" Note2Freq = 3520 Case "a#7", "bb7" Note2Freq = 3729.31 Case "b7" Note2Freq = 3951.07 Case "c8" Note2Freq = 4186.01 Case "c#8", "db8" Note2Freq = 4434.92 Case "d8" Note2Freq = 4698.63 Case "d#8", "eb8" Note2Freq = 4978.03 Case "e8" Note2Freq = 5274.04 Case "f8" Note2Freq = 5587.65 Case "f#8", "gb8" Note2Freq = 5919.91 Case "g8" Note2Freq = 6271.93 Case "g#8", "ab8" Note2Freq = 6644.88 Case "a8" Note2Freq = 7040 Case "a#8", "bb8" Note2Freq = 7458.62 Case "b8" Note2Freq = 7902.13 Case Else Stop End Select End Function Private Sub Timer1_Timer() If (GetAsyncKeyState(vbKeyEscape) And 1) = 1 Then ProgQuit = True Unload Me End If End Sub