BLOG main image
분류 전체보기 (17)
궁시렁 (1)
리버싱 (0)
컴쟁이의 연구실 (11)
배워보자 (2)
좋은 곳 (0)
여행 (0)
독서 (1)
idea (0)
Visitors up to today!
Today hit, Yesterday hit
daisy rss
^0^range.net
2023. 2. 22. 18:15

Github에서는 마크다운 문서가 잘 보이는데, 현재 스킨에서는 문제가 있네.

이건 나중에 고민해보자.

 

RapidJson Library 사용 방법.pdf
0.21MB

 

_<>_HTML 삽입

미리보기할 수 없는 소스

RapidJson 사용 방법

C++에서 json을 처리하기 위해 library를 찾아보다가 rapidjson이 성능이 좋다고 들었다. 샘플과 구글링을 통해 필요한 기능을 여차저차 구현하였지만, 훗날 rapidjson을 다시 사용할 일이 생긴다면 사용법을 이해하는데 시간이 걸릴 것이다. 그래서 나중에 쉽게 참고할 수 있도록 이해한 것들을 기록으로 남겨두고자 한다.(문서 버전: v230223)

RapidJson 특징

  • C++ 코드로 작성, header파일만 포함시켜서 빌드 가능, 별도 외부 library 종속성 없음
  • JSON 처리 속도 우수, JSON 문법 호환성도 양호한 편
  • 입력스트림의 문자열을 자동으로 감지하여 처리, 기본 문자형은 UTF8 인코딩
  • MIT라이선스로 상업 목적으로 사용 가능, 제작자는 중국 Tencent 업체 직원

주의점

    • 이 문서는 rapidjson v1.1.0을 기준으로 설명함
    • json문자열내 멤버명와 문자열값은 모두 큰 따옴표("")로 감싸져야 한다.
      특히 파이썬 애플리케이션과 JSON데이터를 교환시 꼭 큰따옴표를 사용하자.
    • json문자열내 주석(#)이 포함된 경우 파싱이 실패하게 된다.
    •  

{
# 2023-02-21 Generated by XX System

    • "project": "랜섬웨어 대응 훈련",

...

    •  
    • json문자열값에 역슬래쉬(Back-Slash)문자를 포함해야된다면 연속된 역슬래쉬 2개 문자로 표현해야 함.
      문자열값에 포함된 역슬래쉬는 Escape문자로 인식되어 파싱에 실패할 수 있다.
    •  

{"username": "dragon\user"} 인 경우, {"username": "dragon\\user"} 로 변환 사용

    •  
    • rapidjson은 문자열을 유니코드로 처리하기 때문에 GetString()이 반환한 문자열 포인터를 strlen() 함수로 길이를 구해서는 안된다. 상황에 따라 정상적인 유니코드 문자가 NULL문자로 해석되어 정확한 길이를 반환하지 않는 경우가 존재하기 때문이다. 정확한 문자열 길이를 구한다면 GetStringLength() 함수를 이용해야 한다.
    •  

Value& v = doc["SomeMemberName"];
int len1 = strlen(v.GetString());
int len2 = v.GetStringLength();
// 문자열이 "a\u0000b" 이라면, len1은 1이 저장되고, len2는 3이 저장됨

      •  
      • (Move semantics) Value객체를 통해 좌변으로 할당시 우변의 값은 없어지므로(Null 초기화된 객체), 할당후 재사용 금지.
        성능 향상을 위해 대입연산시 깊은 복사가 발생하지 않도록 Library가 설계됨"Move Semantics"가 되는 경우는 Value객체의 대입 연산(operator=) 외에도 AddMember(), PushBack() 함수 호출시에도 동일하게 적용된다. 한번 인자로 전달된 Value객체는 Null초기화되므로, 임시 Value객체를 만들어 전달하는 것이 편리하다. 이런 경우 임시 개체를 적절한 값 참조로 변환할 수 없으므로 Move() 함수를 통해 전달해야 한다고 한다.
      •  

Value arr(kArrayType);

      •  

arr.PushBack(Value().SetInt(42), d.GetAllocator()); // fluent API style
arr.PushBack(Value(43).Move(), d.GetAllocator()); // same as above
arr.PushBack(Value("Hello").Move(), d.GetAllocator());

    •  
    •  

Value a(100);
Value b(200);
a = b; // 우변인 b는 Null이 설정됨, a는 100값이 설정됨

  •  
  • (문자열 데이터 보관 전략) 상수 문자열(const string)의 포인터를 Value객체에서 보관하는 방법과, 내부에 복사본을 만들어 보관하는 방법이 있으니 구현시 참고하자. 다음 예제 소스에서는 str2와 str3이 모두 outlive_string 을 참조하는데, str2는 상수 문자열로 취급하여 포인터만 보관하였고, str3은 내부에 복사본을 더이상 참조하지 않는 전략을 사용했다. 결과적으로 str3은 outlive_string 에 변경이 발생하여도 내부 데이터에는 변경이 발생하지 않게 되었다.
  • void string_strategy() { CHAR outlive_string[] = "hello world"; Document doc(kObjectType); Value str1; Value str2; Value str3; // 문자열 보관 전략 1) 상수 문자열 포인터 보관 str1.SetString("hello world"); // 문자열 보관 전략 2) 상수 문자열은 아니지만, // 상수 문자열 포인터로 취급하여 보관 str2.SetString(StringRef(outlive_string)); // 문자열 보관 전략 3) Value객체에 문자열을 복사하여 보관 str3.SetString(outlive_string, doc.GetAllocator()); _ASSERTE( str1 == "hello world" ); _ASSERTE( str2 == "hello world" ); _ASSERTE( str3 == "hello world" ); // str2, str3이 참조한 outlive_string에 변조 발생! // str2, str3에 담긴 데이터는 문제없을까? strncpy(outlive_string, "HELLO", 5); _ASSERTE( str2 != "hello world" ); _ASSERTE( str3 == "hello world" ); }

활용 팁

본 문서 설명에 사용된 샘플 JSON 문자열(UTF-8 인코딩된 문자열로 가정)은 다음과 같다.

{
    "project": "랜섬웨어 대응 훈련",
    "localip": "192.168.11.17",
    "macaddr": "ab-cd-ef-hi-jk-lm",
    "osver": "Windows 10",
    "buildnum": 19044,
    "hostname": "dragon\\user",
    "username": "user"
}

1. rapidjson 헤더 포함 및 namespace 정의

#include "./rapidjson/document.h"
#include "./rapidjson/writer.h"
#include "./rapidjson/prettywriter.h"
#include "./rapidjson/stringbuffer.h"
#include "./rapidjson/pointer.h"
#include "./rapidjson/rapidjson.h"
using namespace rapidjson;

2. Value와 Document 객체 소개

rapidjosn은 파싱된 JSON문서 구조는 최상단 루트 Value가 자식 Value들을 포함하는 구조이다. 최상단 루트 Value는 사실 Document 클래스가 되며, Value클래스가 제공하는 멤버관리 기능을 동일하게 제공하면서 JSON문서를 파싱할 수 있는 기능도 제공한다.

JSON을 DOM(Document Object Mode) 트리형태로 분석한 모습

Value클래스는 저장될 수 있는 데이터 타입은 다음과 같다. 이 중 Object타입과 Array타입은 또다른 멤버 또는 요소를 포함할 수 있는 컬렉션 타입이다.

static const char* kTypeNames[] = 
{ "Null", "False", "True", "Object", "Array", "String", "Number" };

Value클래스는 데이터 타입을 확인할 수 있는 IsXXX() 함수들과, 데이터에 접근/설정할 수 있는 GetXXX(), SetXXX() 함수들을 제공한다(컬렉션은 멤버 및 요소를 다루는 함수가 별도 제공).

Value nullObj; // 타입을 지정하지 않으면 Null 타입으로 초기화 된다
Value obj(kObjectType);
Value arr(kArrayType);
Value numInt(1);
numInt.SetInt(2);
Value numDouble(3.14);

_ASSERTE(nullObj.IsNull() == TRUE);
_ASSERTE(obj.IsObject() == TRUE);
_ASSERTE(arr.IsArray() == TRUE);
_ASSERTE(numInt.GetInt() == 2);
_ASSERTE(numDouble.GetDouble() == 3.14);

3. Json문자열을 Document 객체로 변환후 멤버 접근하기

rapidjson에서 문자열은 기본적으로 UTF8 인코딩 처리하므로, Document객체의 Parse()함수 호출시 UTF8 인코딩된 json문자열을 전달해야 올바르게 파싱할 수 있다. 또는 프로젝트에 맞는 인코딩을 typedef문으로 정의하여 사용할 수 도 있다.

CStringA jsonStr = CT2A(strReport, CP_UTF8);

Document doc;
doc.Parse(jsonStr);

Document 객체에서 hostname, username 등 JSON 멤버에 대한 값을 구한다. 이때도 UTF8로 처리된 것을 현재 VC프로젝트 기본문자열 타입으로 변환시켜주어야 한다.

CString project = CA2T(doc["project"].GetString(), CP_UTF8);
CString hostname = CA2T(doc["hostname"].GetString(), CP_UTF8);
CString username = CA2T(doc["username"].GetString(), CP_UTF8);
_tprintf(_T("project: %s\n"), project);
_tprintf(_T("hostname: %s\n"), hostname);
_tprintf(_T("username: %s\n"), username);

위 예시는 간단하게 c++에서 json문자열을 로딩하여 멤버에 접근하는 방법을 설명하였지만, 개발시에는 다양한 상황을 고려하여 에러 체크를 강화해야할 것이다.

bool basic_json_string_load()
{
    CStringA jsonStr = CT2A(strReport, CP_UTF8);

    Document doc;
    ParseResult ok = doc.Parse(jsonStr);
    if (!ok)
    {
        _tprintf(_T("JSON parse error: %d (offset %u)\n"), ok.Code(), ok.Offset());
        _tprintf(_T("%s\n"), strReport);
        return false;
    }

    if (!doc.IsObject())
        return false;
    //    혹은 상황에 따라 Document가 Array로 시작하는 경우를 체크함
    //if (!doc.IsArray())
    //    return false;

    //  멤버에 접근하기 위해 멤버 포함여부와 타입 체크
    _ASSERTE(doc.HasMember("project"));
    _ASSERTE(doc["project"].IsString() == TRUE);

    //    필요한 멤버에 접근
    CString project = CA2T(doc["project"].GetString(), CP_UTF8);
    _tprintf(_T("project: %s\n"), project);
    ... 생략 ...

    return true;
}

4. Document객체를 Json 문자열로 변환하기

Document객체를 전송(저장)하기 위해 Json문자열로 변환시 다음 코드를 참고하자. PrettyWriter대신 Writer 클래스를 사용하면, 포맷터 적용없이 Json 문자열로 변환된다.

void print_json_prettify(Document& doc)
{
    StringBuffer buffer;
    PrettyWriter<StringBuffer> writer(buffer);
    doc.Accept(writer);

    CString jsonReport = CA2T(buffer.GetString(), CP_UTF8);
                        _tprintf(_T("%s\n"), jsonReport);
}

5. Document 객체내 멤버에 Pointer로 손쉽게 추가/수정/삭제 하기

Document 객체안 멤버 관리는 Pointer사용하는 것이 가장 간편한 방법 같다. rapidjson 제작자도 이를 위해 헬퍼(Helper) 함수를 제공였다. CreateValueByPointer(), EraseValueByPointer(), GetValueByPointer(), SetValueByPointer() 함수를 활용해 멤버들을 관리할 수 있다.

다음 예제는 'project', 'buildnum' 멤버값을 변경하고, Number타입을 가지는 새로운 'userseq'멤버를 추가하였다. 이후 'macaddr' 멤버를 삭제하고 'hello/there' 오브젝트 멤버와 'hello/world' 배열 멤버를 새롭게 생성하였다.

    //    project 멤버값 변경
    //    SetValueByPointer() 구현이 인자로 전달된 문자열을 내부에 복사하여 보관 처리됨
    //    물론 Value("문자열").Move() 형태로도 전달 가능
    SetValueByPointer(doc, "/project", (LPCSTR)CT2A(_T("RapidJSON 테스트"), CP_UTF8));

    if (Value* pBuildNum = GetValueByPointer(doc, "/buildnum"))
        pBuildNum->SetInt(pBuildNum->GetInt() + 1000);

    //SetValueByPointer(doc, "/userseq", 19214598);        // will not compile
    SetValueByPointer(doc, "/userseq", Value(19214598).Move());

    //    macaddr 멤버 삭제
    EraseValueByPointer(doc, "/macaddr");

    //    새로운 멤버 및 자식멤버까지 동시 생성 -> there멤버는 null로 최초 할당됨
    CreateValueByPointer(doc, "/hello/there");

    //    새로운 멤버 배열 생성 -> world멤버배열은 [null]로 할당됨
    CreateValueByPointer(doc, "/hello/world/0");

6. 오브젝트(Object) 관리하기

오브젝트 자료형은 키-값 쌍으로 구성된 컬렉션으로, 오브젝트내 각 멤버의 키는 문자열형을 사용해야 한다. 멤버를 추가할 수 있는 AddMember() 함수와 삭제할 수 있는 RemoveMember(), EraseMember()를 사용할 수 있다.

void work_with_json_object(Document& doc)
{
    Value o(kObjectType);

    //    오브젝트에 멤버 추가
    o.AddMember("string", "hello world", doc.GetAllocator());
    o.AddMember("message", "rapidjson is powerful", doc.GetAllocator());
    o.AddMember("int", 123, doc.GetAllocator());
    o.AddMember("double", 3.14, doc.GetAllocator());
    o.AddMember("arr", Value(kArrayType).Move(), doc.GetAllocator());

    //    멤버 삭제
    o.RemoveMember("message");

    static const char* kTypeNames[] = 
    { "Null", "False", "True", "Object", "Array", "String", "Number" };

    //    반복자를 통해서 Object에 포함된 모든 멤버에 접근
    for (Value::ConstMemberIterator itr = o.MemberBegin();
        itr != o.MemberEnd(); ++itr)
    {
        printf("Type of member %s is %s\n",
            itr->name.GetString(), kTypeNames[itr->value.GetType()]);
    }

    //    Document(doc)객체에 Value(o)객체를 추가
    doc.AddMember("new_json_object", o.Move(), doc.GetAllocator());
    //    Value o 객체의 데이터는 doc객체로 Move Semantics되므로, Null초기화 됨
    _ASSERTE(o.IsNull() == TRUE);

    print_json_prettify(doc);
}

7. 배열(Array) 요소 관리하기

배열 관리 방식은 std::vector 클래스를 사용하는 방식과 비슷한 API를 제공하므로 어렵지 않게 사용할 수 있다.

void work_with_json_array(Document& doc)
{
    Value& arr = doc["hello"]["world"];

    //    배열 초기화
    arr.Clear();

    //    새로운 값 추가
    arr.PushBack("First Element", doc.GetAllocator());

    for (SizeType i = 1; i <= 3; ++i)
        arr.PushBack(i, doc.GetAllocator());

    arr.PushBack(Value("Last Element").Move(), doc.GetAllocator());

    //    첫번째 요소 삭제
    arr.Erase(arr.Begin());

    _tprintf(_T("====== 배열인덱스를 통해 배열 접근 =======\n"));

    //    0부터 arr배열의 크기-1까지 i값을 증가시키면서 배열 인덱스를 통해 접근
    for (SizeType i = 0; i < arr.Size(); ++i)
    {
        const Value& v = arr[i];

        if (v.IsString())
        {
            _tprintf(_T("%d: \"%s\"\n"), i, CA2T(v.GetString(), CP_UTF8));
        }
        else if (v.IsInt())
        {
            _tprintf(_T("%d: %d\n"), i, v.GetInt());
        }
    }

    _tprintf(_T("\n====== 반복자를 통해 배열 접근 =======\n"));

    //    std::vector 사용하는 것처럼, iterator를 통해 접근하는 방법
    for (Value::ConstValueIterator itr = arr.Begin(); itr != arr.End(); ++itr)
    {
        if (itr->IsString())
        {
            _tprintf(_T("\"%s\"\n"), CA2T(itr->GetString(), CP_UTF8));
        }
        else if (itr->IsInt())
        {
            _tprintf(_T("%d\n"), itr->GetInt());
        }
    }
}

마치며

이 문서는 가장 기초적인 rapidjson 사용 방법에 대해서만 설명하였지만, 심도깊은 내용(유니코드 문자열 인코딩 처리, SAX-style API 처리방법 등)은 공식 사이트 강좌(Tutorial)를 참고하기 바란다.

참고 자료

_<>_HTML 삽입

미리보기할 수 없는 소스

2023. 1. 28. 22:07

김세중 스케이트 강사님의 기술 습득 순서

초급

푸쉬오프(Push Off)
틱택(Tic Tac)
엔드워크(end walk)기초
엔드워크(end walk) - 프론트사이드
엔드워크(end walk) - 백사이드
엔드오버(end over)

중급 이상

알리(Ollie)
샤빗(shuvit)
페이키 알리(fakie ollie)
페이키 샤빗(fakie shuvit)
프론트사이드 180 알리(frontside 180 ollie)
백사이드 180 알리(frontside 180 ollie)
팝샤빗(pop shuvit)
페이키 팝샤빗(fakie pop shuvit)
널리 프론트사이드 샤빗(nollie frontside shuvit)
널리(nollie)
프론트사이드 하프갭(frontside halfcab)
백사이드 하프갭(frontside halfcab)
프론트사이드 팝샤빗(frontside popshuvit)
페이키 프론트사이드 팝샤빗(frontside popshuvit)
킥플립(kickflip)
페이키 킥플립(fakie kickflip)
힐플립(healflip)
페이키 힐플립(fakie healflip)
널리 백사이드 180(nollie backside 180)
널리 프론트사이드 180(nollie frontside 180)
널리 백사이드 팝샤빗(nollie backside popshuvit)
스위치 팝샤빗(switch pop shuvit)

트릭이 익숙해지면 경사, 곡면에서 연습하는 것이 좋습니다. - 김세중 강사

 

2022. 11. 22. 13:56

김세중 강사님의 스케이트보드 강좌

; 초보들이 익혀야 할 기술을 상세하고 체계적으로 잘 가르쳐 주심

https://www.youtube.com/@sejung_eeda

 

Yushi & maschi

; 아버지와 아들같은데 일본인 특유의 섬세함과 디테일을 짧은 영상에 핵심만

; 담아서 가르쳐 주는 것 같고, 아들과 스케이트보드로 함께 하는 모습이 보기 좋음

https://www.youtube.com/channel/UCujcJ8bh2qoTrcEIG_tKZ2w

 

NOLLIE SKATEBOARDING | スケートボードのすべて

; 일본 사이트인데, 체계적으로 기술이 잘 분류해두었다.

https://www.nollieskateboarding.com/

 

스케이트 보드 영상이 많음

https://www.youtube.com/@originalpunk/featured

 

프리스케이트기술까지, 다양한 기술들을 찬찬히 잘 설명해줌

https://www.youtube.com/@SarahParkMatott

 

달려가면서 스케이트보드 타기 기술

; 07:02 경에서 보면 달려가면서 스케이트에보드에 올라타는 방법 설명

https://www.youtube.com/watch?v=KTJnEIipufg&ab_channel=TacticsBoardshop 

 

end walk, end over 부드럽게 잘하는 동영상

https://www.youtube.com/watch?v=SBePDFF2eYo&ab_channel=FreestyleTricktips 

https://www.youtube.com/watch?v=SaPXuBLbeFk

 

알리 8분 가르침

https://www.youtube.com/watch?v=qmu95vp7UpU&ab_channel=NeverStopImproving 

 

알리를  3D 표현으로 자세하게 설명

https://www.youtube.com/watch?v=PlAyejbnYsE&ab_channel=whythetrick 

 

알리의 타이밍에 관하여

https://www.youtube.com/watch?v=5ZhMXWkPsWw&ab_channel=JustKeepSkating 

 

카우보이같은 아저씨, 알리연습하는 방법

https://www.youtube.com/watch?v=7BZbvIIr-VM&ab_channel=SkateParkLessons

 

널리 스케이트보드 코리아

; 단계별 연습하는 방법이 나옴, 쉬운 설명

https://www.youtube.com/watch?v=8p7CmDIK7k0&ab_channel=NOLLIESKATEBOARDINGKOREA 

 

 

 

2022. 9. 13. 23:23

lrzsz 명령어는 zmodem 프로토콜을 이용하여한 telnet, ssh 터미널에서 파일전송을 가능하게 해주는 명령어이다.
없으면 apt-get install lrzsz 명령어로 설치할 수 있다.

mobaXterm이라는 것을 최근에 사용하였는데 putty보다 기능이 많고 편리하였다.

문득 rz, sz 명령어를 지원하는 지 궁금해서 찾아보니, 지원하고 있었다.

리눅스내 파일을 터미널 밖으로 빼기

sz <밖으로 보낼 파일명>

┌──(kali㉿kali)-[~]
└─$ sz test.dat
▒*B00000000000000

mobaXterm에서 연결된 터미널에서 컨트롤키를 누르고 우측마우스를 누른다.
팝업메뉴가 보여지고, 그중 "Receive file using Z-modem" 을 선택하면, 저장할 위치를 선택하는 다이얼로그가 뜬다. 적절한 위치에 해당 파일을 저장하면 된다.

터미널안 리눅스로 파일 넣기

rz

┌──(kali㉿kali)-[~]
└─$ rz
▒z waiting to receive.**B0100000023be50

마찬가지로 컨트롤+마우스우클릭 하면, 팝업메뉴가 나온다. 여기서 "Send file using Z-modem"을 선택하고, 리눅스쪽으로 보낼 파일을 선택하면 된다.

2022. 8. 6. 11:21

EQL 정리

sysmon이벤트에 대해서 다양한 조건으로 손쉽게 검색하기 위해 만들어진 것 같다.
https://github.com/endgameinc/eql 에서 복제한 후 설치하면 된다.

Endgame사가 Elastic에 인수된 이후, EQL을 Elasticsearch에서 통합되어 사용가능하다고 한다.

단점은 eql 프로그램이 직접 evtx를 로드할 수 없고, 꼭 json형태로 변환해서 사용해야 한다.

evtx를 json으로 변환해주는 툴을 사용했지만, 에러만 나고 변환이 안되었다.
https://github.com/vavarachen/evtx2json
사용예) python evtx2json.py process_files --files sysmon.evtx

그래서 EQL홈페이지에 나온방법으로 JSON형태로 변환시킬 수 밖에 없었다.

Get-WinEvent -filterhashtable @{logname="Microsoft-Windows-Sysmon/Operational"} -Oldest | Get-EventProps | ConvertTo-Json | Out-File -Encoding ASCII -FilePath sysmon.json

중간에 Get-EventProps는 별도 작성된 함수이기 떄문에 다음을 참조하여 먼저 Import 시켜주어야 한다
https://github.com/endgameinc/eqllib/blob/master/utils/scrape-events.ps1 


위와 같이 sysmon.json을 추출하면, 이 파일을 대상으로 eql을 이용하여 쿼리할 수 있다.

예) eql query -f sysmon.json "generic where CommandLine == '*powershell*'"

그런대 홈페이지에서 제공하는 예제들은 Sysmon의 데이터필드명에 대해 Normalized을 수행하여 필드명이
조금씩 다르고 새롭게 추가된 부분도 있다. 
eql 명령어으로 Nomalized을 처리해주는 방법을 찾을 수 없어, eqllib을 다시 설치했다.

git clone https://github.com/endgameinc/eqllib.git
python setup.py build
python setup.py install
eqllib -h
eqllib query -f sysmon.json --source "Microsoft Sysmon" "process where process_name in ('ipconfig.exe', 'netstat.exe', 'systeminfo.exe', 'route.exe')"

eqllib의 명령행 인자를 찾아보니 convert-data 라는 부분이 있어 도움말을 확인했다

$ eqllib convert-data -h                                                                          
usage: eqllib convert-data [-h] [--encoding ENCODING] [--format {json,jsonl,json.gz,jsonl.gz}] [--source {security,MITRE Cyber Analytics Repository,Endgame Platform,Microsoft Sysmon}] input-file output-file

positional arguments:
  input-file            Input JSON file
  output-file           Output JSON file

options:
  -h, --help            show this help message and exit
  --encoding ENCODING, -e ENCODING
                        Encoding of input file
  --format {json,jsonl,json.gz,jsonl.gz}
  --source {security,MITRE Cyber Analytics Repository,Endgame Platform,Microsoft Sysmon}, -s {security,MITRE Cyber Analytics Repository,Endgame Platform,Microsoft Sysmon}
                        Data source

컨버팅 해보니 컨버팅도 잘 되었다.

$ eqllib convert-data --source "Microsoft Sysmon" --format json sysmon.json sysmon_normalized.json
Found 11565 events
Converted 11547 events
                                                                                                                                                                                                                                            
$ eql query -f sysmon_normalized.json '| count event_type' 
{"count": 4407, "key": "network", "percent": 0.3816575733956872}
{"count": 7140, "key": "process", "percent": 0.6183424266043128}
$

이제 eql을 이용하여 궁극적인 아토믹블루 쿼리를 해볼 수 있다.
https://eqllib.readthedocs.io/en/latest/atomicblue.html

 

process where process_name in ('powershell.exe', 'cmd.exe', 'wmic.exe', 'wscript.exe') and descendant of [process where process_name in ('excel.exe', 'winword.exe', 'powerpnt.exe', 'outlook.exe', 'hwp.exe')]


eql> search process where process_name="hwp.exe"
=============================================================================================================================================
 pid    ppid   process_name   command_line                                                                                                   
=============================================================================================================================================
 5804   5064   Hwp.exe        "C:\Program Files (x86)\Hnc\Hwp80\Hwp.exe" "C:\Users\Kim\Documents\3??-???-????.hwp" 
 5804          Hwp.exe         
 7440   5064   Hwp.exe        "C:\Program Files (x86)\Hnc\Hwp80\Hwp.exe" "C:\Users\Kim\Documents\2021.09.06 ????? ???(??).hwp" 
 7440          Hwp.exe         
 6768   5064   Hwp.exe        "C:\Program Files (x86)\Hnc\Hwp80\Hwp.exe" "C:\Users\Kim\Documents\????_??_?_???_??_??_??_????_????.hwp" 
 6768          Hwp.exe         
 3960   5064   Hwp.exe        "C:\Program Files (x86)\Hnc\Hwp80\Hwp.exe" "C:\Users\Kim\Documents\????+??+??+??+?+???+??+??+??+????_????.hwp" 
 3960          Hwp.exe         
=============================================================================================================================================
8 results found
eql> search process where ppid in (5804, 7440, 6768, 3960)
========================================================================================================================================================================================================================
 pid    ppid   process_name      command_line                                                                                                                                                                           
========================================================================================================================================================================================================================
 1456   5804   msiexec.exe       C:\Windows\System32\MsiExec.exe -Embedding F353968286C344C5C813D596B5823AF5 E Global\MSI0000 
 6680   5804   msiexec.exe       C:\Windows\syswow64\MsiExec.exe -Embedding A580338B47C3ECA6C027595877571259 E Global\MSI0000 
 4944   5804   msiexec.exe       C:\Windows\syswow64\MsiExec.exe -Embedding 94E5B8CD4FD39B745DCFD3CBAD6C788B E Global\MSI0000 
 5880   5804   msiexec.exe       C:\Windows\syswow64\MsiExec.exe -Embedding E55FED014CB3A2074462C9998210212B E Global\MSI0000 
 6672   6768   conhost.exe       \??\C:\Windows\system32\conhost.exe 0xffffffff -ForceV1 
  760   3960   conhost.exe       \??\C:\Windows\system32\conhost.exe 0xffffffff -ForceV1 
 5820   5804   msiexec.exe       c:\Windows\syswow64\MsiExec.exe -Embedding 716F7153F5ABB0E570A58E155D1A2820 E Global\MSI0000 
 4464   5804   msiexec.exe       C:\Windows\syswow64\MsiExec.exe -Embedding BEF7ABDDF77959BA25985587CDC3B5E2 E Global\MSI0000 
 4224   5804   msiexec.exe       C:\Windows\syswow64\MsiExec.exe -Embedding 4318E41F08BBA4BD29BF42960F782EEF 
 4936   5804   HimTrayIcon.exe   "C:\Program Files (x86)\Hnc\Common80\HimTrayIcon.exe" 
 1872   5804   gbb.exe           "C:\Program Files (x86)\Hnc\Common80\ImgFilters\gs\gs8.60\bin\gbb.exe" "C:\Users\Kim\AppData\Local\Temp\Hnc\BinData\EMB00001f0c32a9.eps" "C:\Users\Kim\AppData\Local\Temp\gsb21CF.tmp" 
 3476   5804   gswin32c.exe      "C:\Program Files (x86)\Hnc\Common80\ImgFilters\gs\gs8.60\bin\gswin32c.exe" @C:\Users\Kim\AppData\Local\Temp\gsa21CF.tmp 
  924   7440   HimTrayIcon.exe   "C:\Program Files (x86)\Hnc\Common80\HimTrayIcon.exe" 
 4088   6768   HimTrayIcon.exe   "C:\Program Files (x86)\Hnc\Common80\HimTrayIcon.exe" 
 4912   3960   HimTrayIcon.exe   "C:\Program Files (x86)\Hnc\Common80\HimTrayIcon.exe" 
========================================================================================================================================================================================================================
15 results found

 

근대, 이제는 detection_rule 로 넘어갔다고 한다.
ELK 에서 EQL, KQL을 이용한 탐지규칙을 적용한 것이다.

 

그러나 간단하게 쿼리를 통한 조사할때에는 여전히 유용한 도구이다.


Process 생성관계를 Tree구조로 보고 싶어서 찾아보니, 
파워쉘로 구현된 소스가 있었다.

https://github.com/gtworek/PSBits/blob/master/DFIR/GetSysmonTree.ps1





참고: https://www.elastic.co/kr/blog/getting-started-eql
Introducing Event Query Language | Elastic Blog
The No Hassle Guide to Event Query Language (EQL) for Threat Hunting (varonis.com)