Quantcast
Channel: Visual Basic 6.0 - Superior Source Code
Viewing all articles
Browse latest Browse all 181

Tempest Test for Windows

$
0
0

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.



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:

PrivateDeclareSub FillMemory Lib "kernel32.dll" Alias "RtlFillMemory" (ByRef Destination As Any, ByVal Length AsLong, ByVal Fill AsByte)
PrivateDeclareFunction SetDIBits Lib "gdi32.dll" (ByVal hDC AsLong, ByVal hBitmap AsLong, ByVal nStartScan AsLong, ByVal nNumScans AsLong, ByRef lpBits As Any, ByRef lpBI As BITMAPINFO, ByVal wUsage AsLong) AsLong
PrivateDeclareSub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds AsLong)
PrivateDeclareFunction SetWindowPos Lib "user32.dll" (ByVal hWnd AsLong, ByVal hWndInsertAfter AsLong, ByVal x AsLong, ByVal y AsLong, ByVal cx AsLong, ByVal cy AsLong, ByVal wFlags AsLong) AsLong
PrivateDeclareFunction GetAsyncKeyState Lib "user32.dll" (ByVal vKey AsLong) AsInteger
 
 
PrivateType BITMAPINFOHEADER
biSize AsLong
biWidth AsLong
biHeight AsLong
biPlanes AsInteger
biBitCount AsInteger
biCompression AsLong
biSizeImage AsLong
biXPelsPerMeter AsLong
biYPelsPerMeter AsLong
biClrUsed AsLong
biClrImportant AsLong
EndType
 
PrivateType RGBQUAD
rgbBlue AsByte
rgbGreen AsByte
rgbRed AsByte
rgbReserved AsByte
EndType
 
PrivateType BITMAPINFO
bmiHeader As BITMAPINFOHEADER
bmiColors(255) As RGBQUAD
EndType
 
 
Dim PicW AsLong
Dim PicH AsLong
Dim Pix() AsByte
Dim BMI As BITMAPINFO
 
PrivateType Note
Freqency AsSingle
Duration AsLong
EndType
 
Dim Song() As Note
 
Dim ProgQuit AsBoolean
 
PrivateSub Form_Activate()
Dim y AsLong
Dim n AsLong
Dim z AsByte
Dim Freq AsSingle
Dim FrameRate AsLong
Dim FrameDuration AsSingle
Dim LineDuration AsSingle
Dim LineRate AsSingle
 
FrameRate = 60
FrameDuration = 1 / FrameRate
LineDuration = FrameDuration / PicH
LineRate = 1 / LineDuration
 
SetWindowPos Me.hWnd, -1, 0, 0, 0, 0, &H201
 
For n = 0 ToUBound(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 ThenExitSub
Next n
Unload Me
EndSub
 
PrivateSub Form_Load()
Dim i AsLong
Dim NotesStr AsString
 
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
EndWith
For i = 0 To 255
With .bmiColors(i)
.rgbRed = i
.rgbGreen = i
.rgbBlue = i
EndWith
Next i
EndWith
 
Open"song.txt"ForBinary Access Read As #1
NotesStr = String$(LOF(1), vbNullChar)
Get #1, 1, NotesStr
Close #1
 
Song() = String2Notes(NotesStr, 300)
 
GetAsyncKeyState vbKeyEscape
Timer1.Enabled = True
EndSub
 
 
PrivateFunction String2Notes(ByVal NotesStr AsString, ByVal Duration AsLong) As Note()
Dim NoteStrings() AsString
Dim Notes() As Note
Dim n AsLong
 
NoteStrings() = Split(NotesStr, "")
ReDim Notes(UBound(NoteStrings))
For n = 0 ToUBound(Notes)
With Notes(n)
SelectCase NoteStrings(n)
Case"."
.Freqency = 0
.Duration = Duration / 2
Case"-"
.Freqency = Notes(n - 1).Freqency
.Duration = Duration
CaseElse
.Freqency = Note2Freq(NoteStrings(n))
.Duration = Duration
EndSelect
EndWith
Next n
String2Notes = Notes()
EndFunction
 
PrivateFunction Note2Freq(ByVal NoteName AsString) AsSingle
SelectCase 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
 
CaseElse
Stop
EndSelect
EndFunction
 
 
PrivateSub Timer1_Timer()
If (GetAsyncKeyState(vbKeyEscape) And 1) = 1 Then
ProgQuit = True
Unload Me
EndIf
EndSub



Viewing all articles
Browse latest Browse all 181

Trending Articles