이번에는 개인적으로 유용하게 쓰고 있는 무료 오픈소스 닷넷 디컴파일러 겸 디버거인 dnSpy를 소개해보고자 합니다.

 

C나 C++같은 언어로 작성되서 빌드된 ELF나 PE 파일같은 네이티브 바이너리 파일들은 IDA Pro나 ghidra같은 툴로 pseudo code 디컴파일 및 정적 분석이 가능합니다. 물론 100% 복구가 안되기 때문에 적당한 휴리스틱 알고리즘을 이용해서 pseudo code 수준으로 보여줍니다.

 

하지만 중간 언어가 있는 닷넷이나 자바로 작성된 프로그램의 경우 훨씬 쉽게 디컴파일이 됩니다. 자바의 경우 jd-gui, 안드로이드의 경우 JEB를 많이 쓰는데 .NET으로 작성된 프로그램의 경우는 어떤걸 쓰면 좋을지 모르실 분들도 있을 것 같습니다.

 

닷넷 프로그램의 경우 오픈소스 SW인 dnSpy를 사용하면 매우 편리합니다.

 

심지어 개인이 만든것으로 보입니다. 

github.com/dnSpy/dnSpy

 

dnSpy/dnSpy

.NET debugger and assembly editor. Contribute to dnSpy/dnSpy development by creating an account on GitHub.

github.com

깃허브 URL은 위와 같고요, 우측 탭에 있는 release로 가서 다운받으시면 됩니다.

릴리즈를 누르면 아래와 같은 화면이 나타나게 됩니다.

dnSpy는 자체도 C#, 닷넷으로 개발되어서 윈도우에서만 구동이 가능합니다.

32bit 닷넷 바이너리를 디컴파일, 디버깅 하고자 한다면 dnSpy win32를 다운받으시면 되고,

64bit 닷넷 바이너리를 디컴파일, 디버깅 하고자 한다면 dnSpy win64를 다운받으시면 됩니다.

 

다운받은 뒤 압축만 풀면 쉽게 사용할 수 있습니다.

 

.NET으로 작성된 윈도우 앱과, Unity 앱도 디버깅이 가능합니다.

 

일단 디컴파일을 통한 닷넷 앱 분석뿐만 아니라, 동적 디버깅도 가능하며, 디버깅 중 인자값을 변경하거나 하는 기능들도 가능한 것으로 알고 있습니다.

 

간혹 닷넷 앱을 분석할 일이 있을 때 사용을 하는데, 생각보다 기능이 더 많을것으로 보이며, 추후에 닷넷 앱 분석을 더 하게 될 일이 있으면 글에 내용을 추가하여 작성하도록 하겠습니다.

 

더 읽어보기

jaeseokim.tistory.com/84

I tried hack.lu ctf 2020 several easy-web challs. There are write-ups.

FluxCloudFluxCloud Serverless (1.0 and 2.0)

I tried both challenge with same solution. I think I first found solution for 2.0, it also worked to 1.0 version challenge.

It provides node.js server source code.

 

There are a few files in zip file. I carefully audited the code.

In this code, the flag is returned by router.get('/flag');

But it is not that simple, because to reach that app.js code, we should passthrough the serverless/index.js router.

router for /:deploymentId/ handles deploymentRouter and then do waf, after then do app function.

 

But there is interesting concept, that is the billing system.

the app function and waf function is wraped by billed function. billed function is defined in serverless/billing.js

billed function check if the money in account is sufficient to pay the cost for traffic. 

When the demo server created, the virtual account is goes up, with some money. Everytime the billed function is called, the money reduces. I didn't audit that code exactly, maybe the money of deployment server is stored in database implemented by redis. 

The account for waf and for app is different. If I can make deplete only account for WAF, not app, the waf is disabled, then I can access the flag!

 

Taking advantage of try-catch phrase in serverless/index.js /:deploymentId/ router, I tried to trigger exception in waf function.

Auditing waf.js code, it checks multiple encoded url and body with recursive function. With too much call of recursive function call, the stack overflow will be triggered. So, I made a HTTP request a thousands of encoded string like %25252525252525.

If the error in serverside occurs, the response is "rip". I tried that request more times to exhaust ACCOUNT_SECURITY to suppress waf functionality.

Finding response header, X-Billing-Account exists. It means, ACCOUNT_SECURITY deposit is bankrupt.

Let's try to access flag!

Cool.

2.0 version chall could be beated with same solution.

web - Confession

Client send graphql query to server. I googled graphql vulenerabilities.

medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696

 

GraphQL — Common vulnerabilities & how to exploit them

Hello there! how you doin? , Bilal Rizwan here & I hope everyone is safe in this time of crisis and making complete use of your…

medium.com

I tried introspect query to server.

The response tells me something.

I checkd the response carefully.

Then I found there is the schema object named accessLog with properties name, args, timestamp. So I tried graphql for fetch that data.

(id in variable field is random value)

I can get a bunch of accessLogs. There are some hash values.

 

I treid to decyprt sha256 hash from online sha256 decryptor. 

The first one was "f", the second one was "fl", the third is "fla", and fourth is "flag".

There are no more sha256 database to decrypt more hashes.

I wrote simple script to get full flag.

#!/usr/bin/env python3

import string
import hashlib
candid = string.printable
flag = "flag"
hashes = """0577f6995695564dbf3e17ef36bf02ee73ba10ab300caf751315615e0fc6dd37
9271dd87ec1a208d1a6b25f8c4e3b21e36c75c02b62fafc48cf1327bac220e48
95f5e39cb28767940602ce3241def53c42d399ae1daf086c9b3863d50a640a81
62663931ff47a4c77e88916d96cad247f6e2c352a628021a1b60690d88625d75
5534607d1f4ee755bc11d75d082147803841bc3959de77d6159fca79a637ac77
52a88481cc6123cc10f4abb55a0a77bf96d286f457f6d7c3088aaf286c881b76
7ffcb9b3a723070230441d3c7aee14528ca23d46764c78365f5fdf24d0cdef53
532e4cecd0320ccb0a634956598c900170bd5c6f1f22941938180fe719b61d37
a4b24c8f4f14444005c7023e9d2f75199201910af98aaef621dc01cb6e63f1d1
1092c20127f3231234eadf0dd5bee65b5f48ffbdc94e5bf928e3605781a8c0d1
1e261929cc13a0e9ecf66d3e6508c14b79c305fa10768b232088e6c2bfb3efa3
0bb629dfb5bf8a50ef20cfff123756005b32a6e0db1486bd1a05b4a7ddfd16c7
0141c897af69e82bc9fde85a4c99b6e693f6eb390b9abdeda4a34953f82efa4b
c20ee107ba4d41370cc354bb4662f3efb6b7c14e7b652394aaa1ad0341e4a1c9
d6b977c1deb6179c7b9ac11fb2ce231b100cf1891a1102d02d8f7fbea057b8a0
fb7dc9b1be6477cea0e23fdc157ff6b67ce075b70453e55bb22a6542255093f1
70b652dad63cabed8241c43ba5879cc6d509076f778610098a20154eb8ac1b89
26f4fc4aba06942e5e9c5935d78da3512907fe666e1f1f186cf79ac14b82fcad
c31c26dbbcf2e7c21223c9f80822c6b8f413e43a2e95797e8b58763605aaca0d
eb992e46fb842592270cd9d932ba6350841966480c6de55985725bbf714a861d
c21af990b2bd859d99cfd24330c859a4c1ae2f13b0722962ae320a460c5e0468
ebf2b799b6bf20653927092dae99a6b0fc0094abc706ca1dce66c5d154b4542d
07a272d52750c9ab31588402d5fb8954e3e5174fcab9291e835859a5f8f34cf9
5a047cba5d6e0cf62d2618149290180e1476106d71bd9fdb7b1f0c41437c2ff5""".split("\n")

def hash(v):
    return hashlib.sha256(v.encode()).hexdigest()

for hashval in hashes:
    for c in candid:
        if hash(flag + c) == hashval:
            flag += c
            print (flag)
            break
print ("Flag is " + flag)

The flag is flag{but_pls_d0nt_t3ll_any1}

개요

이 글은 리눅스 민트에서 도커 컨테이너를 설치하다가 겪은 간단한 에러를 해결한 경험 공유를 하고자 작성했습니다.

 

일단 리눅스 민트는 우분투라고 생각하고 이것저것을 설치하면 된다고 하는데, 그래서 리눅스 민트에서 도커 컨테이너를 설치하면서 도커 공식 홈페이지의 Debian 기준 설치 가이드라인을 따라갔었습니다.

docs.docker.com/get-docker/

 

Get Docker

 

docs.docker.com

위 링크로 가면 도커 설치법이 나옵니다.

일단 리눅스에 설치를 할 것이니, 리눅스를 눌렀죠.

docs.docker.com/engine/install/debian/

 

Install Docker Engine on Debian

 

docs.docker.com

일단 데비안 기준으로 도커 설치법을 하나하나 따라가면서 터미널에 명령어를 쳤습니다.

 

아마 이쯤이었을 것입니다. add-apt-repository 명령어가 자꾸 안되는 현상이 있었습니다.

Malformed repository name 라는 메시지가 자꾸 뜹니다.

 

그러다가 아래 링크를 봤습니다.

linuxhint.com/install_docker_linux_mint/

$(lsb_release -cs)가 들어갈 부분에 bionic 이라는 string이 대신 들어가 있습니다.

 

해결법

sudo add-apt-repository "deb https://download.docker.com/linux/ubuntu bionic stable"

위와 같이 입력하면 됩니다. 보면 [arch=amd64]라는 문자열이 빠져있죠?

그리고 나머지는 도커 공식 홈페이지에서 하라는데로 그대로 하면됩니다.

 

원인파악

정확한 이유는 아닌데, 아마 민트에서 쓰는 add-apt-repository의 다른 버전이 설치가 된 경우가 있을 수 있는데, 그 경우 [arch=amd64]와 같은 문자열이 들어있는 경우를 체크를 못하는 상황이 있는 것 같습니다.

 

사실 add-apt-repository의 심볼릭 링크를 따라가서 처리하는 파이썬 스크립트를 하나하나 분석해보다가 알게된 내용 입니다.

 

도커 설치의 경우만 그런게 아니라 add-apt-repository로 추가 레포지토리를 추가하고 뭔가 설치를 해야 하는 경우 리눅스 민트에서 있을 수 있는 에러입니다.

+ Recent posts