Be myself :: '분류 전체보기' 카테고리의 글 목록 (2 Page)

달력

42024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

'분류 전체보기'에 해당되는 글 116건

  1. 2016.02.13 StudyAid 2
  2. 2016.01.30 PinTool을 이용한 Instruction 추적하기, 간단한 ctf 풀이
  3. 2016.01.28 [algospot]Synchronizing Clocks
  4. 2016.01.26 [pwnable.kr]rsa_calculator
  5. 2016.01.07 Demon using nc.traditional
  6. 2016.01.07 [Algospot]PICNIC
  7. 2015.12.24 [pwnable.kr]maze
  8. 2015.12.22 [pwnable.kr]nuclear
  9. 2015.12.18 [pwnable.kr]alloca
  10. 2015.11.20 [picoctf 2015]Repeated XOR 4

StudyAid

project 2016. 2. 13. 01:53


StudyAid.zip

그냥 심심풀이로 간간히 만든 프로그램. 



끄면 위와 같이 tray로 감 ㅋㅋ


네이버 켈린더를 웹뷰로 띄어주는 화면. 앱처럼 만들고 싶어서 그냥 웹뷰로 만들어봄




공부할꺼 선택하고 시간설정후 타이머 동작. 시간 끝나면 총 공부시간 xml로 저장됨. 설정전에 블로그와 연동해야하는기능이 존재(블로그 포스팅으로 총 공부시간 xml형태로 저장함. 그 후 그 포스팅을 읽어서 총 공부시간 load함)


저거랑 원래는 Winhttp.dll 에서 WinHttpConnect  같은거 후킹해서 사이트 차단기능까지 만드려 했으나.. 크롬에서 동작하지 않아서(나중에 리버싱해서 뭘 후킹해야 하는지 알아내야 겠다) 장난감 만드는건 여기서 마무리..


혹시나(그럴 사람은 없겠지만) 사용하실분은 설명서 필요하시면 댓글 달아주세요 ㅋㅋ


*소스코드 : https://github.com/flack3r/StudyAid



Posted by flack3r
|


hypercomputer.tar.gz


PinTutorial.pdf

깔끔하게 보고 싶으신 분들은 위 pdf파일을 받아주시길..

제일 간단하게 프로그램의 Instruction을 추적하는 Pintool을 만들어 보겠다. Pintool을 만든다는 것은 Pin의 플러그인을 만든다는 느낌으로 만들면 된다. Pin은 JIT의 형태로 생각하면 된다. 자세한 것은 매뉴얼을 참고하자.

[1] instruction 추적하기

일단 타겟 프로그램을 다음과 같이 작성한다.

패스워드를 입력받고 0x31337이면 cong를 출력하는 프로그램이다. 다음과 같이 Main부분의 instruction만을 뽑아오도록 간단한 핀툴을 만든다.

#include <stdio.h>
#include <iostream>
#include "pin.H"
 
using namespace std;
 
#define START 0x4005FD
#define END 0x40065F
INT32 Usage()
{
         PIN_ERROR("this pintool print a trace of memory address\n");
         return -1;
}
 
void printip(void* ip)
{
         printf("address: %p\n",ip);
}
 
void Instruction(INS ins, VOID* v)
{
         long int a = (long int)INS_Address(ins);
         if(START<=a && a<=END)
         {
                 printf("Instruction \n");
                 INS_InsertCall(ins,IPOINT_BEFORE, (AFUNPTR)printip, IARG_INST_PTR, IARG_END);
         }
}
 
void Fini(INT32 code, VOID *v)
{
         cout << "Fini code: " << code << endl;
}
 
int main(int argc,char* argv[])
{
         if(PIN_Init(argc,argv))
                 return Usage();
 
         INS_AddInstrumentFunction(Instruction,0);
         PIN_AddFiniFunction(Fini,0);
 
         PIN_StartProgram();
         return 0;
}

}

코드에 대해 설명하자면 main에서 INS_AddInstrumentFunction 함수로 각 instruction이 실행될 때 실행되는 코드를 등록한다. Instruction함수를 보면 INS_Address로 각각 instruction이 실행될 때의 주소 값을 구해 main함수 내의 instruction의 주소 값만 뽑아온다. 또 각 instruction에 대해 INS_InsertCall을 이용해 instruction이 실행되기 전에 호출되는 callback 함수를 등록한다. 여기선 printip을 등록한다 printip에 넘어가는 인자는 IARG_INST_PTR이라는 인자가 넘어가는데 매뉴얼을 참고해 보면 이건 instruction의 주소 값이다.

다음과 같이 make.rules를 변경하고 make로 컴파일해서 돌려보자.

필자는 hyper.cpp이라는 이름으로 저 소스코드를 저장하였고 따라서 위와 같이 make 룰을 변경하였다. 그 다음 make를 통해 컴파일 하자.

그리고 다음과 같이 실행시키자.(root로 실행하여야 한다.)

이것과 ida로 본 instruction을 하나하나 비교해보자

위의 결과를 비교한 결과 내릴 수 있는 결론은 다음과 같다. 0x4005fd~400611까지 한 묶음, 0x40061B~0x400627까지 한 묶음, 0x400631~0x400639까지 한 묶음…[즉 BBL단위로 묶음] 이런 식으로 routine이 분기되기 전까지 Instruction함수가 호출되고 분기되고 난 후 INS_InsertCall() 으로 등록한 printip함수가 모조리 호출된다.

[2] 비밀번호 맞추기

위와 같이 instruction의 Opcode가 CMP이면 해당 오퍼렌드의 두번 째 비교 값을 가져와서 뿌려준다. 결과는 다음과 같다.

 

#include <stdio.h>
#include <iostream>
#include "pin.H"
 
using namespace std;
 
#define START 0x4005FD
#define END 0x40065F
INT32 Usage()
{
         PIN_ERROR("this pintool print a trace of memory address\n");
         return -1;
}
 
void Instruction(INS ins, VOID* v)
{
         long int a = (long int)INS_Address(ins);
         if(START<=a && a<=END)
         {
                 if(INS_Opcode(ins) == XED_ICLASS_CMP )
                 {
                          UINT64 value = INS_OperandImmediate(ins,1);
                          printf("value is 0x%lx \n",value);
                 }
                 
         }
}
 
void Fini(INT32 code, VOID *v)
{
         cout << "Fini code: " << code << endl;
}
 
int main(int argc,char* argv[])
{
         // Pin initiate
         if(PIN_Init(argc,argv))
                 return Usage();
 
         INS_AddInstrumentFunction(Instruction,0);
         PIN_AddFiniFunction(Fini,0);
 
         PIN_StartProgram();
         return 0;
}

 

[3] [2013 Plaid ctf] hypercomputer-1(bin 100)

문제 파일을 열어보면 다음과 같다.

hello함수에서 배너를 출력하고 CalcResult에서 원래 문자열을 조작해서 flag를 만들어 둔다. CalcResult나 다른 함수들을 리버싱 하면 알겠지만 쓸대없이 usleep과 많은 while문,for문을 만나게 된다. 따라서 핀툴로 이러한 루틴을 다 없애주면 flag를 줄것이다 J 아래의 코드는 그 조작을 한 핀툴을 작성한 것.

#include "pin.H"
#include <iostream>
#include <fstream>
#include <unistd.h>
 
int new_usleep(useconds_t usec)
{
         return 0;
}
 
void Image(IMG img, void *v)
{
         for(SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym))
         {
                 string funcname = PIN_UndecorateSymbolName(SYM_Name(sym),UNDECORATION_NAME_ONLY);
                 if(funcname      == "usleep")
                 {
                          RTN rtn = RTN_FindByAddress(IMG_LowAddress(img)+SYM_Value(sym));
                          if(RTN_Valid(rtn))
                          {
                                   RTN_Open(rtn);
                                   RTN_Replace(rtn, (AFUNPTR) &new_usleep);
                                   RTN_Close(rtn);
                          }
                 }
         }
}
 
void xor_rax(CONTEXT *ctx)
{
         PIN_SetContextReg(ctx, REG_RAX,0);
}
 
void mov_rax_rdx(CONTEXT* ctx)
{
         ADDRINT rdx = PIN_GetContextReg(ctx, REG_RDX);
         PIN_SetContextReg(ctx, REG_RAX, rdx);
}
 
void delete_insns(BBL bbl)
{
         for(INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins))
         {
                 INS_Delete(ins);
         }
}
 
VOID Trace(TRACE trace, VOID *v)
{
    for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
        if(BBL_NumIns(bbl) == 2) {
            INS ins1 = BBL_InsHead(bbl);
            INS ins2 = INS_Next(ins1);
            if(INS_Disassemble(ins1) == "sub rax, 0x1" && INS_IsBranch(ins2) &&
                    INS_DirectBranchOrCallTargetAddress(ins2) == BBL_Address(bbl)) {
                BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR) &xor_rax,
                    IARG_CONTEXT, IARG_END);
                delete_insns(bbl);
            }
        }
        else if(BBL_NumIns(bbl) == 3) {
            INS ins1 = BBL_InsHead(bbl);
            INS ins2 = INS_Next(ins1);
            INS ins3 = INS_Next(ins2);
            if(INS_Disassemble(ins1) == "sub rax, 0x1" && INS_IsNop(ins2) &&
                    INS_DirectBranchOrCallTargetAddress(ins3) == BBL_Address(bbl)) {
                BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR) &xor_rax, IARG_CONTEXT,
                    IARG_END);
                delete_insns(bbl);
            }
            else if(INS_Disassemble(ins1) == "add rax, 0x1" &&
                    INS_Disassemble(ins2) == "cmp rax, rdx" &&
                    INS_DirectBranchOrCallTargetAddress(ins3) == BBL_Address(bbl)) {
                BBL_InsertCall(bbl, IPOINT_BEFORE, (AFUNPTR) &mov_rax_rdx, 
                    IARG_CONTEXT,IARG_END);
                delete_insns(bbl);
            }
        }
    }
}
 
int main(int argc, char* argv[])
{
         if(PIN_Init(argc,argv))
         {
                 return 0;
         }
 
         PIN_InitSymbols();
 
         IMG_AddInstrumentFunction(Image,0);
         TRACE_AddInstrumentFunction(Trace,0);
 
         PIN_StartProgram();
         return 0;}

}

실행하면 다음과 같다.

이 문제의 설명은 다음의 원문에 잘 설명되어 있다: https://eindbazen.net/2013/04/pctf-2013-hypercomputer-1-bin-100/



'Analysis' 카테고리의 다른 글

Pin 기본 API살펴보기  (0) 2015.08.07
[smt solver]z3py 튜토리얼  (0) 2015.08.06
Pin tool 기본세팅  (1) 2015.07.17
Posted by flack3r
|

[algospot]Synchronizing Clocks

2016. 1. 28. 16:51

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

[pwnable.kr]rsa_calculator

2016. 1. 26. 00:01

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

import os
import sys
​
def main():
	if len(sys.argv) != 3:
		print "[usage]python daemon.py filepath port"
		sys.exit()
​
	while True:
		pid = os.fork()
		if pid == 0:
			os.execlp('nc.traditional','nc.traditional','-v','-e',sys.argv[1],'-l','-p',sys.argv[2])
		else:
			print "child pid %d" %(pid)
			os.waitpid(pid,0)
		
​
if __name__ == "__main__":
	main()

'Python' 카테고리의 다른 글

String과 Integer 변환 정리  (0) 2015.08.25
os.execve 주의  (0) 2015.03.31
str과 repr의 차이  (0) 2015.02.22
with~as 구문  (0) 2015.02.22
개발 시 팁  (0) 2015.02.18
Posted by flack3r
|

[Algospot]PICNIC

2016. 1. 7. 11:09

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

[pwnable.kr]maze

2015. 12. 24. 01:40

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

[pwnable.kr]nuclear

2015. 12. 22. 12:23

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

[pwnable.kr]alloca

2015. 12. 18. 01:03

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

[picoctf 2015]Repeated XOR

crypto 2015. 11. 20. 20:26

문제는 다음과 같다.

encrypted.txt를 보면 다음과 같다.

hex가 잔득 적힌 txt파일이다. 파이썬으로 .decode('hex')해서 바이너리로 만든 다음에 연산하면 될 것 같다.

이 문제는 사실 알면 단순하게 바로 풀 수 있는데 워낙 크립토에 문외한인지라.. 상당히 오랜시간이 걸린 문제다. ㅠㅠ
문제 제목이 힌트인데 Repeated xor 같은 경우는 어떤 key가 주어지고, plain text의 길이만큼 concatenation되어서 문장 전체와 xor하는 암호화 기법이다. 이 것을 복호화 하는 방법은, poly alphabetic cipher를 복호화 하는 방법과 같은데 먼저 키의 길이를 구한다. 키의 길이가 구해지면, 각 키의 길이 만큼 떨어진 문자들을 새로운 N 칼럼으로 만들어서 frequency를 조사하여, 제일 많이 나타나는 문자가 공백이 xor 되어 인크립션 되었을 확률이 높으므로, 원래의 키 값이 드러나게 되는 것이다.

쉽게 말하면 "ABCDEFGHI" 라는 암호화된 문자열이 있고 키의 길이가 3이라고 가정하자. 그렇다면 A,D,G(키의 길이 3칸씩 떨어짐)와 B,E,H 그리고 C,F,I 를 각 칼럼으로 나누고 각각 frequency 를 조사 하여 키 값을 알아내는 방식이다.

키 길이를 구하는 방법은 크게 다음과 같이 두가지로 나뉜다.


1. Kasiski_examination 을 이용한다.https://en.wikipedia.org/wiki/Kasiski_examination
이 방법은 poly alphabetic cipher 이어도 반복되는 문자열이 plain text에 존재하고 같은 치환이 이루어 져서, 암호화 된 텍스트 상에서 반복되는 문자열을 찾아서 그 거리를 각각 구한다. 그리고 그 거리의 최대공약수를 구하고, 그 최대 공약수는 키의 배수가 된다. 천천히 생각해 보면 이해가 될 것이다

그런데 이 방법에는 가장 큰 단점이 존재하는데, key 의 길이의 배수가. 반복되는 문자열 사이의 거리 여야 한다는 것이다. 즉 키의 길이는 6인데 반복되는 문자열 사이의 거리가 20 이라면 나누어 떨어지지 않으므로 이 방법이 무효하다는 것이다. 그래서 더 정확한 다음의 방법을 사용하였다.


2. Hamming Weight 를 이용하는 방법이다. 자세한 설명은 다음의 링크를 참조하자.
https://picoctf.com/crypto_mats/index.html#multi_byte_xor

짧게 설명하자면, encryption 된 문자열끼리 xor 연산을 한다면, 다음과 같다. 암호화 된 문자열을 char enc[] 라는 배열에 있다고 가정한다면 enc[0] ^ enc[1] 은 결국 (평문[0]^key[0])^(평문[1]^key[1]) 이렇게 되는데, 만약 키 길이만큼 떨어진 enc 원소를 xor 한다면( key 길이가 8이라 가정) (평문[0]^key[0]) ^ (평문[8]^key[0]) 이 되므로 평문끼리 xor한 결과가 된다. 그런데 평문끼리(알파벳) xor 한 결과의 Hamming Weight는 2~4 정도 이므로 이를 이용해서 키의 길이를 찾는다. 왼쪽으로 키의 길이라 생각되는 만큼 암호문을 쉬프트하고 원래 암호문과 xor 하여 각각의 바이트들의 Hamming Weight를 구하고 평균을 내서 제일 평균이 작은 키의 길이가 원래 키의 길이일 확률이 높다.

나는 2번을 이용하여 키의 길이가 11임을 알아 내고, frequency를 조사하여 공백(0x20)과 xor하여 원래의 키 값을 알아내었다. (실제 문제 풀이시엔 제일 높은 frequency가 공백이라 생각못하고 'E'라고 생각해서 애를 먹었다...)

풀이는 다음과 같다.

가정한 키의 길이가 11일때 Hamming weight 평균이 2로 가장 작으므로 키의 길이라 생각할 수 있다.
frequency 조사하여 복호화 하면 다음과 같다.



import struct
import string

def key_padding(key,msglen):
	orig_key = key
	result_key = ''
	block = (msglen / len(key))
	left = msglen % len(key)
	for i in range(block):
		result_key += key

	result_key += key[:left]
	return result_key

def HammingWeight(t):
	result = 0
	for i in range(32):
		if (t>>i)&1 == 1:
			result+= 1

	return result

def GetKey(msg):
	if len(msg)%11 != 0:
		print "msg len is not multiple 11"
		return

	keyList = []
	#create block list
	blockList = []
	for i in range(11):
		blockList.append([])

	#devide block
	j = 0
	for tmp in msg:
		blockList[j%11].append(tmp)
		j += 1

	for i in range(11):
		result = {blockList[i].count(x): x for x in blockList[i]}
		keyList.append(chr(ord(result[sorted(result).pop()])^ord(' ')))

	return keyList


def main():
	f = open("encrypted.txt","r")
	buf = f.read().decode('hex')
	f.close()

	################### possible key len is 11########
	# for i in range(1,20):
	# 	Ham = lambda (x,y): HammingWeight(ord(x)^ord(y))
	# 	result = map(Ham,zip(buf,buf[i:]))
	# 	fham = filter(lambda x: x<6, result)
	# 	print "[*]try key len %d " %i
	# 	avg_ham = reduce(lambda x,y: x+y, result)
	# 	avg_ham = avg_ham / len(result)
	# 	print "[-]"+str(avg_ham)
	###################################################

	keyList = GetKey(buf)
	keyList[3] = '\x76'
	#print keyList
	keyList = ''.join(i for i in keyList)
	print "find key %s " %(keyList.encode('hex'))

	pkey = key_padding(keyList,len(buf))
	decode = map(lambda (x,y): ord(x)^ord(y), zip(pkey,buf))
	decode = ''.join(chr(x) for x in decode)
	print decode

if __name__ == '__main__':
	main()

decrypt.py

encrypted.txt



'crypto' 카테고리의 다른 글

[BCTF 2017]Beginner's luck (crypto 40)  (0) 2017.02.05
확장된 유클리드  (0) 2015.05.07
암호 공격방법  (0) 2015.04.25
[펌]python hashlib  (0) 2015.03.21
전반적인 암호화  (0) 2015.02.26
Posted by flack3r
|