TEMPEST HDMI 누출 수신 2

나중에 gnuradio를 기반으로 tempestsdr을 초기화하는 gr-tempest 패키지를 찾았는데 gnuradio이다 보니 로컬로 설치하는 것이 더 편해서 실행해봤는데 usrp를 사용해서인지 실제 효과가 떨어지지는 않았습니다. 문제는 hackrf+ 리샘플링인데 하드웨어가 달라서 발생합니다. 그러나 그림을 가져와서 다시 해결할 수 있는 시뮬레이션된 흐름도도 있습니다. 나는 이것을 성공적으로 플레이했다.디버깅을 통해 다른 샘플 수정이 이루어지면 첫 번째 기사와 유사하게 나타나고 더 괜찮은 그림도 나타납니다. 그래서 자신감이 많이 올라갔어요.

나중에 C++/hackrf로 구현된 이전 아날로그 비디오 복조 프로그램에서 시도하기로 결정했습니다. 아니나 다를까, 해봤다.주요 비밀은 아날로그 비디오 복조에서 모든 종류의 동기화를 제거하고 인터레이스 스캔을 제거한 다음 인내심을 가지고 선폭을 조정하는 것입니다.마지막으로 효과를 향상시키고 무작위 점프를 방지하기 위해 새로 고침 간격을 인위적으로 제한하는 것이 좋습니다.

내 코드는 다음과 같습니다.

#include <iostream>
#include <signal.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <libhackrf/hackrf.h>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <sstream>

using namespace std;
using namespace cv;

int decimate_rate = 1;
//#define original_width_x_height 65100

static volatile bool do_exit = false;
int result;
static hackrf_device* device = NULL;
double sample_rate_hz = 6e6/decimate_rate * 1.951047  ;
double baseband_filter_bw_hz =  1e6 ;
double freq_hz = 395.991*1000000;

Mat frame;
int x = 0;
int y = 0;
int correctX = 0;
int correctY = 0;
int autoCorrectX = 0;
int autoCorrectY = 0;

int width = 2081; //multiple of 347 like 2081 or 1387
int height = 800;

int original_width = width / decimate_rate;
int original_width_x_height = original_width * height;
int inverseVideo = 1;

double maxSignalLevel = 0;
double blackLevel = 0;
double coeff = 0;
double agcSignalLevel = 0;
int pixelCounter = 0;
double contrast = 40;
double bright = 40;

int delay_count = 0;

bool bufferIsFull = false;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

//double grayScaleValues[original_width_x_height];
double grayScaleValues[2000000];

void sigint_callback_handler(int signum) 
{
	cout << "Caught signal" << endl;
	do_exit = true;
}

void draw_pixel(double mag)
{
    if (x >= original_width)
    {
        y += 1;
        x = 0;
    }
    if (y >= height)
    {
        y = 0;
        delay_count++;
        if (delay_count > 3)
        {
            bufferIsFull = true;
            delay_count = 0;
        }
    }

    double num2 = (blackLevel - mag) * coeff * contrast;
    num2 += bright;
    if (num2 > 255)
    {
        num2 = 255;
    }
    if (num2 < 0)
    {
        num2 = 0;
    }
    
    int num = y % height * original_width + x % original_width;
    grayScaleValues[num] = num2;

    x = x + 1;
}
int rx_callback(hackrf_transfer* transfer)
{
    double im, re, mag;
    double num = 0;
    double num2 = 0;
    
    double compare_re;
    for( uint32_t i = 0; i <  transfer->valid_length; i += 2)
    {
        // int8_t(transfer->buffer[i]) -128~127
        
        im = (int8_t(transfer->buffer[i]))/128.0;
        re = (int8_t(transfer->buffer[i + 1]))/128.0;

        compare_re = abs(int8_t(transfer->buffer[i+1])) ;
        if (compare_re > num) 
        {
            num = compare_re;
        }
        
        double mag = sqrt( im * im + re * re);  //mag 0~1.414

        if (mag > num2)
        {
            num2 = mag;
        }
        if (inverseVideo)
        {
            mag = maxSignalLevel - mag;
        }

        pthread_mutex_lock(&mtx);
        draw_pixel(mag);
        pthread_mutex_unlock(&mtx);
        //grey of opencv is 0~255
        //0 is black 255 is white
    } 
    
    maxSignalLevel = maxSignalLevel * 0.9 + num2 * 0.1;
    blackLevel = maxSignalLevel * 0.4;
    coeff = 255 / blackLevel;
    agcSignalLevel = num;

    return 0;
}

void *receiving_function(void *arg)
{ 
    while (do_exit == false)
    {
        sleep(1);
    }
    cout << "Thread Exiting..." << endl;
    pthread_exit(NULL);
}

int main()
{
    pthread_t recv_th;

    signal(SIGINT, &sigint_callback_handler);

    frame = Mat::zeros(height, width, CV_8UC1);

    result = hackrf_init();
    if( result != HACKRF_SUCCESS ) 
    {
        cout << "hackrf_init() failed" << endl;
        return EXIT_FAILURE;
    }
    result = hackrf_open(&device);
    if( result != HACKRF_SUCCESS ) 
    {
        cout << "hackrf_open() failed" << endl;
        return EXIT_FAILURE;
    }

    result = hackrf_set_sample_rate(device, sample_rate_hz);
    if( result != HACKRF_SUCCESS ) 
    {
        cout << "hackrf_set_sample_rate() failed" << endl;
        return EXIT_FAILURE;
    }

    result = hackrf_set_baseband_filter_bandwidth(device, baseband_filter_bw_hz);
    if( result != HACKRF_SUCCESS )
    {
        cout << "hackrf_baseband_filter_bandwidth_set() failed" << endl;
        return EXIT_FAILURE;
    }
    
    result = hackrf_set_freq(device, freq_hz);
    if( result != HACKRF_SUCCESS ) 
    {
        cout << "hackrf_set_freq() failed" << endl;
        return EXIT_FAILURE;
    }

    result = hackrf_set_lna_gain(device, 40);
    if( result != HACKRF_SUCCESS ) 
    {
        cout << "hackrf_set_lna_gain() failed" << endl;
        return EXIT_FAILURE;
    }

    result = hackrf_set_vga_gain(device, 26);
    if( result != HACKRF_SUCCESS ) 
    {
        cout << "hackrf_set_vga_gain() failed" << endl;
        return EXIT_FAILURE;
    }
    
    int err = pthread_create(&recv_th, NULL, receiving_function, NULL);
    if (err != 0)
    {
        cout << "Create thread failed" << endl;
    }
    
    result = hackrf_start_rx(device, rx_callback, NULL); 

    while( (hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false) ) 
    {
        if (bufferIsFull)
        {
            pthread_mutex_lock(&mtx);
            for (int counter = 0; counter < original_width_x_height; counter++)
            {
                int new_x = counter % original_width;
                int new_y = counter / original_width;
                 

                for (int c = 0; c < decimate_rate; c++)
                {
                    frame.at<uchar>(new_y, new_x*decimate_rate + c) =  grayScaleValues[counter];
                }
                grayScaleValues[counter] = 0;
            }   
        
            bufferIsFull = false;
            pthread_mutex_unlock(&mtx);
        }
        imshow("frame", frame);

        if (waitKey(5) == 'q')
        {
            do_exit = true;
            break;
        }
    }

    if (do_exit)
    {
	cout << "Exiting..." << endl;
    }

    result = hackrf_close(device);
    if(result != HACKRF_SUCCESS)
    {
        cout << "hackrf_close() failed" << endl;
    } 
    else 
    {
        cout << "hackrf_close() done" << endl;
    }

    hackrf_exit();
    cout << "hackrf_exit() done" << endl;
    
    pthread_join(recv_th,NULL);
    return 0;
}

컴파일할 명령은 다음과 같습니다.

g++ hackrf_tv_hdmi.cpp -o hackrf_tv_hdmi `pkg-config --cflags --libs opencv` -lhackrf -pthread

관심있는 친구들이 시도해 볼 수 있습니다. 제 모니터는 1920x1080 60Hz로 설정되어 있습니다. 가능한 주파수는 나와 다릅니다.

현재 C++ 버전 코드는 확실히 tempestsdr보다 훨씬 간단하지만 여전히 가장 간단하지는 않습니다.아날로그 비디오 복조를 할 때 많은 중복 코드가 있습니다. 시간이 나면 파이썬 버전으로 정리하도록 하겠습니다.

측정 효과:

SDR, HDMI 누출 신호 2 프로그램 최적화 및 누출 소스 검색 수신_哔哩哔哩_bilibili - https://www.bilibili.com/video/BV1sr4y1G7oL

Supongo que te gusta

Origin blog.csdn.net/shukebeta008/article/details/125438189
Recomendado
Clasificación