안경잡이개발자

728x90
반응형

  킬디스크(Killdisk)는  GRUB 부트로더 단에서 랜섬 노트를 보여주고 주요 디렉토리를 전부 암호화하는 랜섬웨어입니다. 이 랜섬웨어는 리눅스 기반의 변종도 있기 때문에, 간단히 리눅스 기반의 랜섬웨어 감염 환경을 구축하고 싶을 때 사용할 수 있습니다. 참고로 랜섬웨어 파일은 Hybrid Analysis 사이트에서 다운로드받으실 수 있습니다.

 

※ Victim 서버용 OS 구축하기 ※

 

  가장 먼저 Guest OS를 구축합니다. 저는 Ubuntu 16.04 Server용 이미지를 이용해 Guest OS를 설치했습니다. 일단 Host OS에서 Guest에 손쉽게 접속할 수 있도록 Guest 입장에서 SSH를 설치합니다.

 

 

  이제 Guest는 Network 설정을 진행합니다. 기본적으로 네트워크 어댑터를 NAT에 연결합니다. 또한 [Connect Network Adapter]에 정상적으로 체크되어 있는지 확인합니다. 이 과정에서 Guest의 아이피 주소를 확인하기 위해 ifconfig 명령어를 사용해 볼 필요가 있습니다. 결과적으로 다음과 같이 포트포워딩을 진행합니다. 

 

 

※ Host에서 Guest OS의 웹 서버에 접속해보기 ※

 

  SSH를 이용해 개방된 Guest OS에 접속해 볼 수 있습니다.

 

sudo ssh -p 5678 dongbin@127.0.0.1

 

 

  결과적으로 다음과 같이 SCP를 이용하여 랜섬웨어 파일을 전송할 수 있습니다. 저는 Host 입장에서 Guest가 127.0.0.1:5678의 주소를 가지도록 포트포워딩 설정을 진행했으므로, 이를 그대로 이용하여 파일을 전송합니다.

 

sudo scp -P 5678 /home/dongbin/Downloads/ransomware.gz dongbin@127.0.0.1:/home/dongbin/ransomware.gz

 

  결과적으로 다음과 같이 파일이 전송됩니다.

 

 

※ Guest OS에서 Killdisk 실행해보기 ※

 

  Guest OS에서는 다음과 같이 랜섬웨어 압축 파일의 압축을 해제합니다.

 

 

  또한 [Connect Network Adapter] 항목을 체크 해제하고, 네트워크 어댑터를 [Not attached]로 설정합니다. 혹시나 랜섬웨어의 변종이 Host OS를 거치고 랜을 통해 주변 컴퓨터를 감염시킬 수도 있으므로 랜섬웨어 분석을 할 때는 네트워크 설정에 유의할 필요가 있습니다.

 

 

  결과적으로 Guest OS에서 ransomware 파일에 실행 권한을 부여하고 실행합니다.

 

sudo chmod +7 ransomware
sudo ./ransomware

 

 

  실행한 이후에 곧바로 ls, cd 와 같은 명령이 동작하지 않게 됩니다.

 

 

  이후에 약 2분 정도의 시간이 소요된 이후에는 감염된 Guest OS의 터미널에 더 이상 아무 내용도 출력되지 않습니다. 이때 재부팅을 진행합니다. (너무 빠르게 재부팅 하는 경우에는 GRUB에서의 랜섬 노트가 제대로 출력되지 않을 수 있습니다.)

 

 

  감염된 Guest OS를 재부팅 하면 다음과 같이 랜섬 노트가 출력됩니다.

 

728x90
반응형

728x90
반응형

  말 그대로 Ubuntu 16.04 OS를 가지는 호스트 PC가 있을 때, 거기에 가상 머신을 설치하여 Ubuntu 16.04 Guest를 만드는 방법을 정리한 글이다.

 

※ Oracle VM VirtualBox ※

 

  가상 머신을 돌리기 위한 도구는 굉장히 다양하지만, Oracle VM VirtualBox를 이용하겠다.

 

  ▶ Oracle VM VirtualBox 경로: www.virtualbox.org/

 

Oracle VM VirtualBox

Welcome to VirtualBox.org! News Flash Important October 27th, 2020We're hiring! Looking for a new challenge? We're hiring a VirtualBox senior developer (Germany/Europe/USA). New October 20th, 2020VirtualBox 6.1.16 released! Oracle today released a 6.1 main

www.virtualbox.org

 

  [Download VirtualBox] 버튼을 눌러 설치 프로그램을 받는다.

 

 

  필자의 Host OS는 Ubuntu 16.04 Desktop이므로, 리눅스(Linux) 배포판을 받는다.

 

 

  자신의 Host OS에 맞는 설치 프로그램을 받는다.

 

 

  디폴트 설정 그대로 확인 버튼만 눌러도 설치가 성공적으로 진행된다.

 

※ Guest OS 설치하기 ※

 

  필자는 Guest OS로 Ubuntu 16.04 Server 프로그램을 사용할 예정이다.

 

  ▶ 우분투(Ubuntu) Download: releases.ubuntu.com/16.04/

 

Ubuntu 16.04.7 LTS (Xenial Xerus)

Select an image Ubuntu is distributed on two types of images described below. Desktop image The desktop image allows you to try Ubuntu without changing your computer at all, and at your option to install it permanently later. This type of image is what mos

releases.ubuntu.com

 

  이어서 64-bit 서버용 이미지를 받았다.

 

 

  [New] 버튼을 눌러 새로운 Guest OS를 설치하자.

 

 

  다음과 같이 이름을 지어준다.

 

 

  그리고 디폴트 설정 그대로 [Next]만 눌러도 무난하게 설치가 가능하다. 이후에 Guest OS 이미지로부터 OS 설치를 진행하기 위해 [Settings] 버튼을 누른다.

 

 

  [Storage]에 들어가 우분투 서버용 이미지 파일을 선택한다.

 

 

  이어서 [Install Ubuntu Server]를 눌러 설치를 진행하면 된다.

 

 

  마찬가지로 기본적인 설정 그대로 [Next]를 눌러도 크게 이슈가 없다. 다만 중간에 OS 사용자명과 패스워드를 입력하라는 메시지가 나오므로 잘 기입해 준다.

 

 

  마찬가지로 이후에 [Next]를 반복하여 넘어가면 다음과 같이 실질적인 설치가 진행된다.

 

 

  결과적으로 OS 설치가 완료되었다.

 

728x90
반응형

728x90
반응형

  CryptoTrooper리눅스 기반의 오픈소스 랜섬웨어(Ransomware)입니다. 간단히 랜섬웨어 실습을 해보고 싶을 때 사용할 수 있습니다.

 

※ Victim 서버용 OS 구축하기 ※

 

  가장 먼저 Guest OS를 구축합니다. 저는 Ubuntu 16.04 Server용 이미지를 이용해 Guest OS를 설치했습니다. 일단 Host OS에서 Guest에 손쉽게 접속할 수 있도록 Guest 입장에서 SSH를 설치합니다.

 

 

  이제 Guest는 Network 설정을 진행합니다. 기본적으로 네트워크 어댑터를 NAT에 연결합니다. 또한 [Connect Network Adapter]에 정상적으로 체크되어 있는지 확인합니다. 이 과정에서 Guest의 아이피 주소를 확인하기 위해 ifconfig 명령어를 사용해 볼 필요가 있습니다. 결과적으로 다음과 같이 포트포워딩을 진행합니다. 간단히 웹 서버도 같이 개방하고자 합니다.

 

 

※ Guest OS에 필요한 라이브러리 설치하기 ※

 

  Guest에서는 apache2 웹 서버와 MySQL을 설치합니다.

 

sudo apt-get install apache2 nginx-common mysql-server postgresql

 

  이후에 MySQL에 접속하여 간단히 설치된 내용을 확인합니다.

 

mysql -u root -p
use mysql;
select host, user, authentication_string from user;

 

  실행 결과는 다음과 같습니다.

 

 

  이후에 간단히 하나의 테이블을 만들고 예시 데이터를 입력합니다.

 

CREATE TABLE CUSTOMER (
    id int(10) NOT NULL,
    name varchar(20) DEFAULT NULL,
    PRIMARY KEY(id)
);

INSERT INTO CUSTOMER VALUES (1, 'Johnson');
SELECT * FROM CUSTOMER;

 

  실행 결과는 다음과 같습니다.

 

 

※ Host에서 Guest OS의 웹 서버에 접속해보기 ※

  포트포워딩을 통해 개방된 웹 서버에 접속해 볼 수 있습니다.

 

 

※ Guest OS에서 CryptoTrooper를 사용하기 ※

 

  이제 Guest OS에서 CryptoTrooper를 사용해 랜섬웨어에 감염되어 봅시다. 먼저 전체 소스코드를 다운로드 받습니다. 그리고 소스코드가 존재하는 경로에 있는 모든 파일들을 루트 디렉토리(/)로 옮깁시다.

 

git clone https://github.com/jdsecurity/CryptoTrooper
cd /
sudo mv $CRYPTOTROOPER_SOURCE_DIRECTORY/* .

 

  실행 결과는 다음과 같습니다.

 

 

  이후에 랜섬웨어를 동작시키는 cipher.sh 스크립트를 실행합니다.

 

sudo /cipher.sh &

 

  실행 결과는 다음과 같습니다. 기본적으로 접근 가능한 디렉토리에 있는 파일들을 모두 감염시킵니다.

 

 

 

※ Host에서 감염된 Guest OS의 웹 서버에 접속해보기 ※

 

  웹 사이트에 접속하면 다음과 같이 랜섬 노트(Ransom Note)를 확인할 수 있습니다.

 

 

※ 감염된 Guest OS에서 복호화 해보기 ※

 

  Guest OS에서는  whiteDecipher.sh 스크립트를 실행하여 암호된 파일들을 암호 해제해 볼 수 있습니다.

 

sudo ./whiteDecipher.sh
sudo /decipher.sh

 

  실행 결과는 다음과 같습니다.

 

 

  이어서 호스트가 다시 접속하면 다음과 같이 복호화 된 것을 확인할 수 있습니다.

 

 

※ Host에서 예시 웹 사이트 만들어 Guest로 옮기기 ※

 

  커스텀 웹 사이트가 랜섬웨어에 감염된 것을 실습하는 방법입니다.

 

 

  ▶ index.html

<html>
    <head>
        <title>Demo Website</title>
    </head>
    <body>
        <h2>Demo Website</h2>
        <p>This is a demo website for demonstrating ransomware infection.</p>
        <h3>
            <a href="./link1.html">Link 1</a>
        </h3>
        <h3>
            <a href="./link2.html">Link 2</a>
        </h3>
    </body>
</html>

 

  ▶ link1.html

 

<html>
    <head>
        <title>Demo Website</title>
    </head>
    <body>
        <h2>Link 1</h2>
        <p>This is link 1.</p>
    </body>
</html>

 

  ▶ link2.html

 

<html>
    <head>
        <title>Demo Website</title>
    </head>
    <body>
        <h2>Link 2</h2>
        <p>This is link 2.</p>
    </body>
</html>

 

  이제 Host OS에서 Guest OS로 파일을 옮깁시다. Host OS 입장에서는 127.0.0.1:5678이 Guest 의 주소가 됩니다. 결과적으로 Guest의 /home/dongbin/web 이라는 경로에 파일들을 옮기는 것입니다.

 

sudo scp -r -P 5678 /home/dongbin/Downloads/demo/ dongbin@127.0.0.1:/home/dongbin/web

 

  실행 결과는 다음과 같습니다.

 

 

  만약에 SSH 접속을 많이 해서 Host Identification이 변경되었다는 내용이 출력되는 경우 /root/.ssh/known_hosts에 작성된 내용을 제거할 수 있도록 합니다.

 

sudo rm /root/.ssh/known_hosts

 

 

  결과적으로 Guest는 다음과 같이 웹 파일을 받게 됩니다.

 

 

  이후에 전달 받은 경로인 /home/dongbin/web을 Apache의 루트 디렉토리로 설정합니다.

 

sudo nano /etc/apache2/apache2.conf

 

  대략 다음과 같은 형태로 작성된 부분이 있습니다.

 

<Directory /var/www/>
    ...
</Directory>

 

  이걸 자신의 경로로 바꿉니다.

 

<Directory /home/dongbin/web/>
    ...
</Directory>

 

  예를 들어 다음과 같이 작성됩니다.

 

 

  이어서 sites-available 경로에 있는 default.conf 파일도 변경합니다.

 

sudo nano /etc/apache2/sites-available/000-default.conf

 

  여기에 적혀 있는 DocumentRoot의 경로를 마찬가지로 변경해 주겠습니다.

 

DocumentRoot /home/dongbin/web/

 

  다음과 같이 변경됩니다.

 

 

  이제 웹 서버를 재부팅합니다.

 

sudo service apache2 restart

 

  이어서 다시 호스트 입장에서 접속하면 다음과 같습니다.

 

 

  참고로 만약 호스트에서 접속했을 때 403 Forbidden 오류가 나온다면, 다음과 같이 루트 디렉토리에 있는 파일들에 대하여 권한을 변경합니다.

 

cd /home/dongbin/web/
sudo chmod o+x ~

 

  이어서 Guest OS에서 다시 CryptoTrooper를 받아서 랜섬웨어 감염을 진행합시다.

 

cd /home/dongbin
sudo rm -rf CryptoTrooper
git clone https://github.com/jdsecurity/CryptoTrooper

cd /
sudo mv $CRYPTOTROOPER_SOURCE_DIRECTORY/* .
sudo /cipher.sh &

 

  실행 결과는 다음과 같습니다.

 

 

  그러면 각종 웹 파일들의 확장자가 .enc로 변경되며 암호화됩니다.

 

  마찬가지로 다시 복호화를 진행하면 정상적으로 호스트에서 파일을 확인할 수 있습니다.

 

 

 

728x90
반응형

728x90
반응형

1. 라즈베리파이에서 Host PC로 다량의 데이터 전송

 

  Host PC 입장에서는 다음과 같이 코드를 작성할 수 있다. Serial 통신을 이용해 계속해서 데이터를 전달 받아 파일에 쓰게 된다. 또한 프로그램이 동작하는 과정에서 주기적으로 통신 속도를 출력하도록 해보았다.

 

import time
import serial

s = serial.Serial("COM7", 115200)
total = 0

start_time = time.time()
last_time = 0 

while True:
    # 가져올 데이터가 존재하는 경우에만 처리
    len = s.inWaiting()
    if len == 0:
        continue

    # 파일을 열어 로그를 작성
    f = open("log.dat", "ab")
    data = s.read(len)
    f.write(data)
    f.close()
    total += len

    # 주기적으로 출력
    passed = time.time() - start_time
    if passed > last_time + 1:
        print(f"total length: {total} bytes")
        print(f"average speed: {total / (1024 ** 2 * passed)} MB/s")
        last_time = passed

s.close()

 

  라즈베리파이에서는 다음과 같이 코드를 작성할 수 있다. 크기가 4096 bytes인 배열에 데이터를 담아서 반복적으로 Serial 통신을 통해 데이터를 전송한다.

 

#include <stdio.h>

int main(void) {
    FILE* file;
    char buf[4096];

    for (int i = 0; i < sizeof(buf); i++) {
        buf[i] = i % 256;
    }

    while (1) {
        file = fopen("/dev/ttyGS1", "r+");
        fwrite(buf, 1, sizeof(buf), file);
        fclose(file);
    }
    return 0;
}

 

  단순히 데이터를 전달받는 것만 작업을 했더니 약 3MB/s 정도의 전송 속도가 나오는 것을 확인할 수 있다.

 

 

 

  다만 필자의 경우 처음에 데이터의 유실이 발생했다. 일단 내가 라즈베리파이에서 데이터를 쓸 때 파일을 "r+" 옵션으로 열었는데, b를 붙여 주는 것을 깜빡 잊어 byte stream으로 데이터를 작성하지 않고 있었다. 그래서 "rb+" 옵션으로 바꾸어주면 해결될 줄 알았다. 하지만 여전히 데이터의 유실이 발생했다.

 

  정확히는 라즈베리파이가 \b10을 보내려고 하면 \b13\b10이 보내지는 것이었다. 다시 말해 \n을 보내려고 하면, 자동으로 앞에 \r가 붙어버리는 문제가 발생했다. 이때 CR(Carriage Return)\r을 의미한다. (아스키코드 13번) 또한 LF(Line Feed)는 New Line와 같은 말로 \n을 의미한다. (아스키코드 10번) 콘솔에서는 CRLF 한 쌍을 줄 바꿈으로 인식하는 경우가 많아서, 시리얼로 LF만 보내도 자동으로 앞에 CR를 붙여 버리는 것이다.

  따라서 라즈베리파이에서 다음과 같은 명령어를 입력한 뒤에 문제가 해결되었다. raw 데이터 자체를 보내도록 하는 것이다.

sudo stty -F /dev/ttyGS1 raw 


  이렇게 raw 모드로 바꾼 이후에는 속도를 확인한 결과 다음과 같이 5MB/s 정도의 전송 속도가 나오는 것을 확인할 수 있었다. 속도에 영향을 미치는 부분으로 raw 모드만 작용했는지는 명확하지는 않은데, 아무튼 이 정도 속도까지는 뽑을 수 있다.

 

 

  아무튼 속도가 빠르기 때문에 3분이면 1GB 정도의 데이터를 보낼 수 있었다. 추가적으로 데이터의 유실이 발생하는지 여부를 체크하는 코드를 짜보자. 데이터를 받는 쪽에서 이용하면 된다.

 

f = open("log.dat", "rb")

data = f.read()

for i in range(len(data) - 1):
    if (data[i] + 1) % 256 != data[i + 1]:
        print("(Invalid) 데이터가 부정확합니다.")
    if i % (1024 ** 2) == 0:
        print(f"{i // (1024 ** 2)}MB checked.")

 

  실행 결과 약 800MB 정도의 데이터를 전달받았으나, 한 치의 오차도 없이 데이터가 모두 전송된 것을 확인할 수 있었다.

 

2. Host PC에서 라즈베리파이로 다량의 데이터 전송

 

  Host PC 입장에서도 Serial 통신을 이용해 대량의 파일을 라즈베리파이에게 전송할 수 있다.

728x90
반응형

728x90
반응형

※ 기초 설정 ※

 

  /boot/config.txt 파일을 열어서 제일 마지막 줄에 다음의 코드를 추가한다.

 

dtoverlay=dwc2

 

  /etc/modules의 마지막 줄에 다음 두 개의 커널 모듈을 넣어주자. 

 

dwc2 
libcomposite 

 

  이후에 Mass Storage Class의 기능을 위해 하나의 블록 디바이스(block device)를 생성한다.

 

mkdir -p /home/pi/images

# 1Gb 이미지 생성
dd if=/dev/zero of=/home/pi/images/usbdisk1.img bs=1048576 count=1024
mkdosfs /home/pi/images/usbdisk1.img

 

※ Configuration 1 ※

 

  첫 번째 Configuration인 /usr/bin/my_usb1을 생성해 보자.

 

sudo touch /usr/bin/my_usb1 # 파일 생성
sudo chmod +x /usr/bin/my_usb1 # 실행할 수 있도록 만들기
sudo nano /usr/bin/my_usb1 # 스크립트 작성하기

 

  구체적인 스크립트는 다음과 같다.

 

#!/bin/bash
cd /sys/kernel/config/usb_gadget/
mkdir -p my_usb
cd my_usb

# 기본적인 USB 클래스 명시
echo 0x1D6B > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB 2.0

# 내가 만들 USB 장치의 기본적인 이름
mkdir -p strings/0x409
echo "0123456789abcdef" > strings/0x409/serialnumber
echo "Dongbin Na" > strings/0x409/manufacturer
echo "My USB" > strings/0x409/product

# 하나의 Configuration 정보 작성
mkdir -p configs/c.1/strings/0x409
echo "My USB Config 1" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower

################# Bulk Transfer 1 #################
mkdir -p functions/acm.usb0
ln -s functions/acm.usb0 configs/c.1/

################# Bulk Transfer 2 #################
mkdir -p functions/acm.usb1
ln -s functions/acm.usb1 configs/c.1/

################# Mass Storage 1 #################
# 첫 번째 이미지 지정하기
FILE1=/home/pi/images/usbdisk1.img

# 해당 이미지에 마운트(mount) 진행하기
mkdir -p ${FILE1/img/d}
mount -o loop,ro, -t vfat $FILE1 ${FILE1/img/d} # 라즈베리 파이 입장에서는 읽기 전용(read-only)

# USB 기능(function) 작성하기 (kernel.org reference 참고하기)
mkdir -p functions/mass_storage.usb0
echo 1 > functions/mass_storage.usb0/stall
echo 0 > functions/mass_storage.usb0/lun.0/cdrom
echo 0 > functions/mass_storage.usb0/lun.0/ro # 호스트 입장에서는 쓰기 가능
echo 0 > functions/mass_storage.usb0/lun.0/nofua
echo $FILE1 > functions/mass_storage.usb0/lun.0/file # 이미지 파일 명시하기

# 만들어진 기능(function) 사용할 수 있도록 설정
ln -s functions/mass_storage.usb0 configs/c.1/

# UDC (Usb Device Controller)
ls /sys/class/udc > UDC

 

※ Configuration 2 ※

 

  두 번째 Configuration인 /usr/bin/my_usb2를 생성해 보자.

 

sudo touch /usr/bin/my_usb2 # 파일 생성
sudo chmod +x /usr/bin/my_usb2 # 실행할 수 있도록 만들기
sudo nano /usr/bin/my_usb2 # 스크립트 작성하기

 

  구체적인 스크립트는 다음과 같다.

 

#!/bin/bash
cd /sys/kernel/config/usb_gadget/
mkdir -p my_usb
cd my_usb

# 기본적인 USB 클래스 명시
echo 0x1D6B > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB 2.0

# 내가 만들 USB 장치의 기본적인 이름
mkdir -p strings/0x409
echo "0123456789abcdef" > strings/0x409/serialnumber
echo "Dongbin Na" > strings/0x409/manufacturer
echo "My USB" > strings/0x409/product

# 하나의 Configuration 정보 작성
mkdir -p configs/c.1/strings/0x409
echo "My USB Config 1" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower

################# Bulk Transfer 1 #################
mkdir -p functions/acm.usb0
ln -s functions/acm.usb0 configs/c.1/

################# Bulk Transfer 2 #################
mkdir -p functions/acm.usb1
ln -s functions/acm.usb1 configs/c.1/

# UDC (Usb Device Controller)
ls /sys/class/udc > UDC

 

※ 스크립트 자동 실행 ※

 

  스크립트를 부팅 시 자동 실행하도록 만들기 위해 /etc/rc.local을 수정한다.

 

sudo nano /etc/rc.local

 

  이후에 exit 0 위쪽 라인에 /usr/bin/my_usb1을 추가하자. 재부팅 이후에 USB device가 잡히는 것을 확인할 수 있다.

 

 

※ 선택적으로 USB Configuration 변경하기 ※

 

  이제 /etc/rc.local에 내용을 더 추가하자.

 

cat /dev/ttyGS0 >> /home/pi/test.dat &

 

 

  기본적으로 test.dat은 첫 번째 USB Configuration 정보를 가지도록 한다.

 

echo A > /home/pi/test.dat

 

  이후에 /etc/rc.local을 아래 내용을 넣는 방식으로 바꾼다. test.dat의 가장 마지막 문자열이 A일 때는 첫 번째 Configuration, B일 때는 두 번째 Configuration을 이용한다.

 

var=$(cat /home/pi/test.dat)
flag="${var: -1}"

if [ $flag == "A" ]
then
    /usr/bin/my_usb1
else
    /usr/bin/my_usb2
fi

 

 

  만약 정상적으로 동작이 안 된다면 동일한 스크립트를 작성한 뒤에 sudo bash 명령으로 실행해보자. 호스트 쪽에서 신호를 보낼 때는 다음과 같이 한다.

 

import serial

s = serial.Serial("COM6", 115200)
s.write(b'A\n')
s.close()
728x90
반응형

728x90
반응형

  미디어파이어(MediaFire)무료 파일 공유 서비스다. 일단 무료로 사용할 수 있으며 정말 편리하게 파일을 올려서 바로 링크를 공유할 수 있기 때문에 필자는 매우 자주 사용한다. 

 

  ▶ MediaFire 회원가입 경로: www.mediafire.com/upgrade/

 

  사이트에 접속하면 다음과 같이 회원가입 플랜이 등장한다. 간단히 BASIC으로 다운로드를 진행할 수 있다.

 

 

  이후에 다음과 같이 회원가입을 진행한다. 참고로 2020년 11월을 기준으로 별도로 이메일 인증은 존재하지 않는다.

 

 

  이제 로그인을 하고 나면 다음과 같이 [UPLOAD] 버튼을 눌러서 바로 파일 업로드를 진행할 수 있다.

 

 

  파일은 그냥 드래그 앤 드롭(Drag & Drop)해서 올리면 된다.

 

 

  이후에 다음과 같이 [Copy Link]를 눌러 링크를 복사할 수 있다.

 

 

  이후에 링크에 접속하면 다운로드(Download) 버튼이 등장한다. 참고로 무료 계정의 경우 광고(ad)가 다수 등장할 수 있기 때문에 다운로드를 받는 입장에서는 유의할 필요가 있다.

 

728x90
반응형

728x90
반응형

  Raspberry Pi Zero WSerial 통신 목적의 USB 디바이스로 사용할 수 있다. 한 번 2개의 Serial 인터페이스를 제공하는 USB 디바이스를 만들어 보았다. 기본적인 환경 설정 파일은 다음과 같다. 경로는 /usr/bin/my_usb로 하였다.

 

#!/bin/bash
cd /sys/kernel/config/usb_gadget/
mkdir -p my_usb
cd my_usb

# 기본적인 USB 클래스 명시
echo 0x1D6B > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB 2.0

# 내가 만들 USB 장치의 기본적인 이름
mkdir -p strings/0x409
echo "0123456789abcdef" > strings/0x409/serialnumber
echo "Dongbin Na" > strings/0x409/manufacturer
echo "My USB" > strings/0x409/product

# 하나의 Configuration 정보 작성
mkdir -p configs/c.1/strings/0x409
echo "My USB Config 1" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower

# 하나의 Serial 통신 기능 추가
mkdir -p functions/acm.usb0
ln -s functions/acm.usb0 configs/c.1/

# 하나의 Serial 통신 기능 추가
mkdir -p functions/acm.usb1
ln -s functions/acm.usb1 configs/c.1/

# UDC (Usb Device Controller)
ls /sys/class/udc > UDC

 

  이로써 두 개의 Serial 인터페이스를 호스트에 제공하게 된다. 기본적인 이름은 /dev/ttyGS0/dev/ttyGS1에 매핑된다. 추가하는 횟수에 따라서 인덱스가 증가하게 된다.

 

1. 단순히 Serial (Bulk Transfer)로 "A" X 4096을 반복적으로 보내는 프로그램

 

  그냥 계속해서 데이터를 이어 붙여 보내기 때문에 r+ 옵션을 사용한다.

 

#include <stdio.h>

int main(void) {
    FILE* file;
    char buf[4096];

    for (int i = 0; i < sizeof(buf); i++) {
        buf[i] = 'A';
    }

    while (1) {
        file = fopen("/dev/ttyGS0", "r+");
        fwrite(buf, 1, sizeof(buf), file);
        fclose(file);
    }
    return 0;
}

 

  간단히 transfer1라는 이름으로 실행 파일을 만들었다.

 

sudo gcc 소스코드 -o transfer1

 

2. 랜덤한 64bits (8 bytes) 데이터를 생성하여 반복적으로 보내는 프로그램

 

  이 경우 파일 내용은 매번 새로 써서 8 bytes 씩 보내는 것이므로 하므로 w+ 옵션을 이용한다. (근데 이렇게 해도 Bulk Transfer의 특성상 가능한 최대한 많은 양의 데이터를 보낸다.)

 

#include <stdio.h>
#include <stdlib.h> // rand()
#include <time.h> // time()
#include <stdint.h> // uint32_t

uint32_t rand_uint32(void) {
    uint32_t r = 0;
    for (int i = 0; i < 32; i++) {
        r = r * 2 + rand() % 2;
    }
    return r;
}

// 4바이트를 읽어 버퍼의 특정 인덱스에 삽입
void val32_to_buf(char* buf, uint32_t val, uint32_t index) {
    buf[index] = val;
    buf[index + 1] = val >> 8;
    buf[index + 2] = val >> 16;
    buf[index + 3] = val >> 24;
}

int main(void) {
    FILE* file;
    char buf[8];
    srand(time(NULL));

    while (1) {
        uint32_t r1 = rand_uint32();
        uint32_t r2 = rand_uint32();

        val32_to_buf(buf, r1, 0);
        val32_to_buf(buf, r2, 4);

        file = fopen("/dev/ttyGS1", "w+");
        fwrite(buf, 1, sizeof(buf), file);
        fclose(file);
    }
    return 0;
}

 

  이어서 transfer2라는 이름으로 실행 파일을 만들었다.

 

sudo gcc 소스코드 -o transfer2

 

※ Serial 통신 프로그램 자동 실행 ※

 

  이후에 /etc/rc.local를 수정한다. 두 프로그램을 백그라운드에서 실행할 수 있도록 한다.

 

stty -F /dev/ttyGS0 raw
stty -F /dev/ttyGS1 raw
/home/pi/transfer1 &
/home/pi/transfer2 &

 

 

  이후에 sudo reboot을 해서 재부팅하자. 그러면 재부팅 이후에 호스트(host) PC 입장에서는 다음과 같이 나온다.

 

 

※ 호스트 쪽 프로그램 작성 ※

 

  호스트 쪽 프로그램은 다음과 같이 pyserial 라이브러리를 이용하여 작성할 수 있다. 그냥 USB 디바이스로부터 데이터를 받아 출력하는 코드다. 윈도우(Windows) OS에서는 Serial USB 장치가 꽂힌 경우 COM 포트로 인식하기 때문에 이를 이용하면 된다.

 

import time
import serial

s = serial.Serial("COM8", 115200)
total = 0

start_time = time.time()
last_time = 0 

while True:
    # 가져올 데이터가 존재하는 경우에만 처리
    len = s.inWaiting()
    if len == 0:
        continue

    data = s.read(len)
    print(data)
    
    time.sleep(1)

s.close()

 

  프로그램을 실행하면 다음과 같이 'A'를 계속해서 받는 것을 알 수 있다.

 

 

※ (추가) Guest가 데이터를 받아서 단순히 파일에 기록할 때 ※

 

  USB device가 호스트(host)로부터 데이터를 받아서 저장할 때는 다음과 같이 한다. 그냥 /dev/ttyGS1에서 파일 읽기를 수행하여 특정한 파일에 쓰는 것(이어쓰기)이다.

 

cat /dev/ttyGS1 >> /home/pi/test.dat

 

  결과적으로 다음과 같이 /etc/rc.local 파일을 수정하면 된다. 기본적으로 cat>> 를 이용하여 파일의 뒤쪽에 쭉 이어 붙여 데이터를 쓸 수 있도록 한다.

 

stty -F /dev/ttyGS0 raw
stty -F /dev/ttyGS1 raw
/home/pi/transfer1 &
cat /dev/ttyGS1 >> /home/pi/test.dat

 

  이제 리부팅 진행한 뒤에 호스트에서 다음과 같은 프로그램을 작성하여 보내보자.

 

import serial

s = serial.Serial("COM6", 115200)
s.write(b'Hello\n')
s.close()

 

  프로그램을 여러 번 실행하면 라즈베리파이에는 다음과 같이 파일의 내용이 쓰인다.

 

728x90
반응형

728x90
반응형

  C언어를 이용해 랜덤한 데이터를 생성해 출력하는 방법은 다양하다. 그중에서 한 가지 방법은 다음과 같다.

 

#include <stdio.h>
#include <stdlib.h> // rand()
#include <time.h> // time()
#include <stdint.h> // uint32_t

uint32_t rand_uint32(void) {
    uint32_t r = 0;
    for (int i = 0; i < 32; i++) {
        r = r * 2 + rand() % 2;
    }
    return r;
}

// 4바이트를 읽어 버퍼의 특정 인덱스에 삽입
void val32_to_buf(char* buf, uint32_t val, uint32_t index) {
    buf[index] = val;
    buf[index + 1] = val >> 8;
    buf[index + 2] = val >> 16;
    buf[index + 3] = val >> 24;
}

int main(void) {
    FILE* file;
    char buf[8];
    srand(time(NULL));

    while (1) {
        uint32_t r1 = rand_uint32();
        uint32_t r2 = rand_uint32();

        printf("%u\n", r1);
        printf("%u\n", r2);

        val32_to_buf(buf, r1, 0);
        val32_to_buf(buf, r2, 4);

        for (int i = 0; i < sizeof(buf); i++) {
            printf("%X", buf[i]);
        }
        printf("\n");
    }
}

 

  컴파일 이후에 실행해 보면 다음과 같이 출력되는 것을 확인할 수 있다. 구체적으로 4 bytes 정수형 데이터 2개를 생성한 뒤에 이를 이용하여 64 bits 데이터를 생성해 낸다.

 

728x90
반응형