SPPNet : Spatial Pyramid Pooling 

in Deep Convolutional Networks for Visual Recognition


SPPNet

 

가장 큰 장점

1. R-CNN은 이미지 한 장당 수천 번의 CNN을 수행함(Time-Consuming).

이미지 안에서 bounding box Selective Search 방법을 사용.

반면에 SPPNet은 딱 한 번 CNN을 수행함(one-pass).

ImageFeature Map에서 어떤 위치에 해당하는 정보를 뽑아냄.

 

2. SPPNet은 이미지의 Scale(확대/축소), Size(크기), Aspect Ratio(종횡비)에 영향을 받지 않음.

 

기존의 CNN의 입력

무조건 고정 크기가 입력됨.

: Fully Connected Layer 때문이다(fixed-length Vector가 필요함).

 

Crop(자르기) : 전체 객체가 들어가지 않는 경우가 발생.

Warp(줄이거나 늘리기) : 원하지 않는 왜곡이 발생.

 

사실, Convolution Layer에는 고정 크기의 입력이 필요하지 않음.

 

BoW(Bag of Words) 기법의 확장


 [Box of Words]


1. Feature Extracting

2. Clustering : K-Means 알고리즘 사용, Codeword 찾아냄

3. Codebook Generation

4. Image Representation : Histogram화 시킴(bin 개수 = Codeword 개수)

5. Learning and Recognition : SVM 등의 방법으로 분류


R-CNN 방법과 SPPNet 방법


[R-CNN]


R-CNNImage 영역(Selective Search 방법으로 수천 개를 만듦.)을 추출하고 Warp 시킴.

원하지 않는 왜곡(Unwanted geometric distortion)이 발생함.

이후 추출한 영역을 CNN으로 학습시킴.

매우 느리다(time-consuming).

 

[Spatial Pyramid Pooling]


SPPNet Convolution 마지막 층에서 나온 Feature Map을 분할하여 평균을 내고 

고정 크기로 만들어버림.

→ '06년 발표된 Spatial Pyramid Matching 방법에서 나옴.    


[Spatial Pyramid Matching]


분할 방법은 “fast” mode of Selective Search

[논문 : “Segmentation as selective search for object recognition,” in ICCV, 2011.]

마지막 Pooling LayerSPP(Spatial Pyramid Pooling)로 대체함.

+ 내부적으로 Global Max Pooling 사용.

분할하는 크기만 동일하면 어떤 Size, Scale, Aspect Ratio를 가진 이미지가 와도 똑같은 크기의 

Vector가 출력됨.(이후 FC Layer에 입력으로 들어감.)

분류기 : 이진 선형 SVM


[Spatial Pyramid Pooling Network Architecture]

 

분할 크기(4-level Spatial Pyramid)

50 bins : {6x6, 3x3, 2x2, 1x1} 12,800-dimension(256x50) representations

30 bins : {4x4, 3x3, 2x2, 1x1}

→ stride를 각각의 크기 별로 따로 적용함.



SPP Layer의 출력

(K * M)-dimensional Vector (K는 마지막 Feature Mapdimension, Mbin의 크기)

 

Training

Single-size training : 224x224 size로만 학습, {3x3, 2x2, 1x1} SPP 사용.

2. Multi-size training : 180x180 and 224x224 두 종류를 학습.

180-Network224-Network의 출력은 동일하다.

? 나누고, 평균을 구해서 뽑기 때문.

Network Switching 방법? Epoch 1180-Network, Epoch 2224-Network... 반복!

 

실험 네트워크


[Test Network Architecture : 1. ZFNet, 2. AlexNet, 3. Overfeat Architecture]


ZFNetAlexNetConvolution Layer5

Overfeat 구조는 FC Layer1x1 Convolution으로 이해한 구조.

Sliding Window 개념 적용 가능, 연산량 감소 but 정확도는 높지 않음.

 

Improves Accuracy 



1. Multi-level Pooling

{6x6, 3x3, 2x2, 1x1}{4x4, 3x3, 2x2, 1x1}의 차이는 거의 없다.

하지만, SPP를 사용한 것과 사용하지 않은 것은 확실한 차이가 있다.

(50 bin pyramid : 34.98/14.14, no-SPP : 35.99/14.76)

 

2. Multi-size Training(그림 참조)

Multi-size SPPNet(Overfeat-7) : 29.68%

Single-size SPPNet : 30.36% / no-SPP : 32.01%


3. Full-image Representations



 다중 조합 뷰가 싱글 Full-Image 뷰보다 더 좋은 경우도 있음.

(We find that the combination of multiple views is substantially better than the single full-image view.)

 

하지만 여전히 Full-Image View는 장점이 있는데

1. 수십 개의 뷰를 조합한 경우에도 추가적인 두 개의 전체 이미지 뷰에서 약 0.2%의 성능 향상이 있음.

2. 전체 이미지 뷰는 원래의 방식과 동일하다.

3. 응용 프로그램에서 이미지 자체를 표현하는 것을 요구할 수 있음.

Detection Result



Positive Sample vs Negative Sample(Data Labeling) 


[Positive Sample and Negative Sample]


positive sample : ground-truth(=GT) Sample을 사용.

negative sample : positive sample과 최대 30% 겹치는 Sample을 사용(IOU 측정법).


[Intersection over Union]


Result 



Conclusion

- SPPNet은 다른 크기, 다른 사이즈, 다른 종횡비를 다루기 위한 유연한 방법이다.

ClassificationDetection에서 높은 정확성, 특히 DNN 기반의 Detection을 크게 빠르게 해줌.



Posted by NDC :


MobileNet v2 : Inverted residuals and linear bottlenecks



MobileNet V2

 

이전 MobileNet 일반적인 Conv(Standard Convolution)이 무거우니 이것을 Factorization

Depthwise Separable Convolution(이하 DSC)을 사용

 

사용한 기법들

1. Depthwise Separable Convolution

2. Inverted Residuals

 


Depthwise Separable Convolution

방식 : Standard ConvolutionSeparate Depthwise Conv. + Pointwise Conv.

 

1) Depthwise Convolution : kernelwidth * height * depth=1 로 설정하고

입력 이미지의 각 Channel 마다 별개로 Convolution 실시

(각 채널마다 독립적으로 Convolution)

 

2) Pointwise Convolution : kernelwidth=1 * height=1 * depth 로 설정하고

Convolution 실시(Network in Network 논문의 1 by 1 convolution과 동일)

 


기존 Convolution Layer의 연산량

DKDKMNDFDF

 

DSC(Depthwise Separable Convolution) Layer의 연산량

DKDKMDFDF + MNDFDF

= DFDFM(DKDK + N)

 

Standard Convolution보다 8~9배 수준의 속도 향상을 가져옴.

 

(추가 1. Batch Normalization 대신 Fused Batch Normalization 사용이 더 좋다.)



Linear Bottlenecks

방식: Residual Learning 방식을 통해 네트워크를 깊게 구성할 경우, 연산량이 많이 늘어나게 된다.

1 by 1 Convolution을 활용해 채널 수를 감소시킴.

(Residual Learning? : 학습을 위한 Weight Layer를 거친 후에, 초기 Input의 값을 더해주는 형태)

 

1) 일반적인 방식

일반적인 3*3 convolution 실시

 

2) Bottleneck 방식

1 by 1 convolution으로 채널 수를 줄이고 3 by 3 convolution을 실시 다시 1 by 1 convolution으로 채널 수를 복구시킴.



Q. Inverted Residual 인가?

A. 기존의 bottleneck(C)은 채널 감소 학습(DSC) 채널 복구 방식이지만,

Inverted Residual(D)은 채널 증가 학습(DSC) 채널 감소 방식이다(Inverted .)

 

Input DataOutput Data의 크기가 작기 때문에 메모리 효율적이다.



Network Architecture





 

1) 19개의 Layer로 구성되어 있음.

2) building block1번 이상의 동일 구조의 반복으로 되어 있다.(parameter n 참조)

 

Posted by NDC :

*** Easy UnpackMe 리버싱하기 ***


2번 Easy Keygen은 패스하고... 이번엔 Reversing.kr 사이트의 3번 문제 Easy UnpackMe 문제를 풀어보겠습니다.


사실 이번 문제는 진정한 Unpack 을 한 것이 아니라, Olly Dbg 플러그인을 사용하여 언팩을 했습니다.


원래 언팩과정이라 하면,


"팩 과정을 찾아내서 그 부분에 BP를 걸고 디버깅을 한다."


로 볼 수 있지만, 저는 초보라 그 부분이 많이 어렵더라고요.


구글에서 검색한 결과,



1. PUSHAD 과정을 찾는다.

- 여기서 PUSHAD 란 PACKING 과정을 위해 모든 Register 들을 Stack 에 PUSH 하는 과정을 의미합니다.


2. 중간을 넘어서, POPAD 과정을 찾는다.

- 여기서 POPAD 란 PACKING 과정이 모두 끝난 후에,

OEP 위치 직전에서 프로그램 실행을 위해 다시 모든 Register 위치에 원래대로 값을 복원시키는 것을 말합니다.



특히 저 POPAD 부분은 EDI 레지스터를 중심으로 봐야 한다는데... 자세한건 더 공부해 보기로 하구요!


오늘은 Unpack 을 쉽게 해주는 Olly Dbg 의 플러그인을 소개하고, OEP(진짜 시작부분, Original Entry Point) 를 어떻게 찾는지 말씀드리겠습니다.



(주의 : 포스트 하단에 정답이 공개되어 있습니다!!!)


-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------


우선 첨부파일 OllyDump.dll 파일을 올려놓았습니다.


 

OllyDump.dll



위 dll 파일을 다운로드 하신 후에,


* OllyDbg 설치 경로 plugin 폴더(없을 경우 생성)


위치에 넣어주시면 됩니다.




들어간 후에...



plugin 폴더를 만들고...(저도 없어서 만들었습니다.)



해당 경로에 잘 넣어줍니다.



-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------



이렇게 플러그인을 넣으셨으면 Olly Dbg 를 들어가서 플러그인 설정을 해주어야 합니다.


디버거를 열어주세요.





들어가서 상단 툴바의 [Options] → [Appearance] 를 들어가주세요.





[Directories] 항목의 하단 [Plugin path:] 칸에 위의 OllyDump.dll 파일을 넣어 준 plugin 폴더의 경로를 넣어줍니다.





새로 입력되었으면, 디버거를 재시작하라는 창이 뜹니다.


[확인] 을 눌러서 창을 끈 후, 디버거를 재시작 해줍니다.





재시작을 하고, 상단에 [Plugins] → [OllyDump] 항목을 들어갈 수 있습니다. (1 Olly Advanced 는 제가 이전에 넣어둔 플러그인 입니다.)



-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------



자, 그러면 플러그인 세팅이 끝났습니다. 이제 이 툴을 가지고 Easy Unpack 문제를 풀어볼게요.



우선 exe 파일을 열어줍니다.





열었습니다. 우측 하단에 [Paused] 상태네요.


바로 플러그인으로 OEP 를 찾아보겠습니다.


상단에 [Plugins] → [OllyDump] → [Find OEP by Section Hop(Trace over)] 를 눌러줍시다.

(Trace into 는 한번에 OEP 까지 가지 않고 함수별로 Stop 됩니다. 분석에는 더 좋겠지만 문제를 풀기 위해서는 over로 한 번에 가는게 좋을 것 같네요.)





우측 하단에 Program entry point 에 속지마세요... 저건 Unpack 전의 EP입니다. OEP 가 아닙니다!





[Plugins] → [OllyDump] → [Find OEP by Section Hop(Trace over)] 를 누르게 되면


우측 하단에 [Paused] 상태에서 [Tracing] 상태로 변한 것을 확인할 수 있습니다.


이 상태로 기다립니다.(몇 초 만에 순식간에 끝나지 않습니다. 조금만 기다립시다.)





OEP 추적이 끝나면 저렇게 작업표시줄에서 깜박입니다.






우측 하단이 [Tracing] 에서 [Paused] 로 바뀌었고, 디버깅 위치가 자동으로 00401150 으로 세팅되어 있습니다.


OEP 추적이 끝난 상태이므로  00401150 이 OEP 라는것을 추측할 수 있습니다.



이 정보를 가지고 Readme.txt 파일을 읽어보면...





답은 저런 방식으로 입력하는 것인가 봅니다.


Reversing.kr 사이트에 가서...





찾았다고 추측하는 주소(00401150) 를 입력하고 좌측의 [AUTH] 를 입력합니다.





Easy Unpack 문제가 해결되었네요!



-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------



원래 정석대로라면 PACK 부분과 PACK 의 종료시점을 찾는게 진정한 Unpacker 이겠지만..


아직은 실력이 많이 모자르다고 생각되네요


조금 더 실력을 기르게 되면 Unpack 과정도 손쉽게 할 수 있지 않을까요?



그래도 Easy Crack 은 3956 분이 해결하셨는데 Easy Unpack 문제는 그의 절반 정도만 해결하셨네요.


아마 저처럼 툴 없이 하시려다가 못 푸신 분들이 다수 계실 것 같습니다.


저도 실력을 빨리 길러서 플러그인 없이 Unpack 하는 날이 오길 바랍니다 ㅎㅎㅎ



>>> Easy Unpack


>>> OllyDump.dll


>>> OEP


>>> Original Entry Point


'보안 & 모의해킹 > 리버싱' 카테고리의 다른 글

[Reversing.kr] - 1. Easy CrackMe  (0) 2018.07.11
Posted by NDC :

*** Easy CrackMe 리버싱하기 ***



처음으로 스스로 (구글의 도움없이) 리버싱을 해냈습니다.


물론 WinAPI 함수는 구글링을 했습니다.


처음부터 끝까지 레지스터의 스택포인터 따라가며, 헥사값을 보며, 동작의 의미를 알고,


그 느낌을 알면 아 이곳에는 이 값이겠구나 추론을 하고(물론 맞췄습니다.)


아무튼...


제가 지금까지 리버싱 공부하면서 수많은 블로그 글들을 참조하였듯이,


이 파일을 해결하지 못하신 분들도 제 블로그를 보시고 제가 따라온 루트를 밟고 꼭 푸시는데 도움이 되었으면 좋겠습니다!


(Easy_CrackMe.exe 파일의 출처는 Reversing.kr 입니다!)



(주의 : 포스트 하단에 정답이 공개되어 있습니다!!!)


-------------------------------------------------------------------------------------------------------------------------------------------------------------


일단 파일을 실행시켜 보겠습니다.



음...비밀번호를 입력해서 correct / wrong 을 맞추는 프로그램이라는 것을 추측할 수 있겠네요.


물론 그 비밀번호는 Flag 가 되겠구요.


일단 아무거나 쳐보겠습니다.



한 번에 맞추면 좋겠지만... 아쉽게도 틀렸네요.


하지만 여기서 큰 힌트를 얻을 수 있는데, 바로 문자열


"Incorrect Password"


입니다.


바로 올리디버그로 열어봅시다.



EP는 00401188이네요.


일단 처음에 생각할 수 있는 것은, 저 위에서 발견한 "Incorrect Password" 문자열을 출력하는 위치를 알아내는 것입니다.


[우클릭] > [Search for] > [All referenced text strings] 를 클릭하여 해당 문자열의 위치를 알아봐야 합니다.




위치는 0040113C 네요.


더블클릭해서 이동해봅시다.



저기 위쪽에 빨간배경(BreakPoint, BP), 브레이크포인트를 걸어놨습니다. 느낌 상 저기서 뭔가가 시작된다는 느낌이 왔습니다.


이 상태에서 F9을 누르면 저 위치까지만 실행됩니다.


저 BP는 풀지 않는 것이 좋습니다. 리버싱 하게 되면서 핵심 동작의 시작부분에 BP를 걸어두는 습관을 기릅시다.



그러면 실행파일이 뜹니다. 문자열을 입력받을 차례입니다.


아래에 보면 GetDlgItemTextA 함수가 있는데, 이는 WinAPI 함수로써, 구글에 어떤 함수인지 검색해 보았습니다.


하지만 느낌상...문자열을 입력받는 함수라는 것을 알 수 있죠?


Get + Dlg(=Dialog) + ItemText(=문자열) + A(=API)


즉, 대화상자에서 문자열을 Get 하는 API 라고 해석할 수 있습니다.




저기서 컨트롤이란...MFC에서 볼 수 있는 입력창(Edit Control)을 말하는 것 같네요.


아무튼 문자열을 입력받습니다.


어떤 동작인지 알았으니까 더 볼 필요 없겠죠? 일단 문자열을 입력하고 확인을 누릅니다.



이후에 F8로 쭉쭉 넘어갑니다.


GetDlgItemTextA 함수 아래까지 왔습니다. CMP 명령어로 어떤 두 가지를 검사하네요.


이후 ZF(제로 플래그)를 띄울지 안띄울지 판단 후, 이 ZF로 점프여부도 판단하겠네요.


왜냐면... 그 아래에 JNZ(Jump if Not Zero)가 있으니까요 ㅎㅎ


일단 두 가지가 무엇인지 볼게요.


하나는 ESP+5 의 주소의 값이고, 하나는 61입니다.


61은 딱 보니...아스키 값인 것 같네요. 61은 아스키 값으로 a를 의미합니다. (0x61 = 'a')


그럼 ESP+5의 위치에 무엇이 있는지 보겠습니다.


우선 현재의 ESP 값은



0019F6F0 입니다. 여기서 +5를 해주게되면 0019F6F5가 됩니다.



0019F6F0 의 줄에는 80 00 60 10 이 있고, 0019F6F4 줄에는 46 44 53 41 이 있네요. 그리고 그 아래 0019F6F8 줄에는 00 44 53 41 이 있습니다.


윈도우 운영체제는 Little Endian 방식을 사용합니다.


위의 값들은 실제로 이런 방식으로 들어가 있습니다.



61이 아스키 값이라고 추측해보면, 저 숫자들은 아스키 값이라는 것을 추측할 수 있습니다.


41 = A    /    53 = S    /    44 = D    /    46 = F

41 = A    /    53 = S    /    44 = D    /    00 = (NULL)


ASDFASD 가 나왔네요. 이는 저희가 저 위에서 입력한 값이네요.


즉, ESP+5 와 61을 비교한다는 것은, 두번째 자리가 a인지 아닌지를 검사한다는 것을 알 수 있습니다.


몇자리가 될 지는 모르겠지만, 하나는 알게됬습니다. 문자열의 두 번쨰 자리의 값은 'a'가 되어야 합니다.


a가 아닐 경우에는 00401135 주소로 점프하는데, 이는 Incorrect Password 문자열을 출력(틀렸음을 의미)하게 되는 함수가 있습니다.


=> @a@@@....


이번 문자열은 틀렸으니까 다시 Ctrl + F2 를 눌러서 재실행 시킨 후, 아무거나 입력합니다. 대신 두번째 자리는 a로 합니다.



대충 이렇게 입력했습니다.


다시 그 위치로 가볼까요.



두 번째 자리에 a를 입력했기 때문에 실패조건을 넘어갑니다.


이번엔 ASCII "5y"라는 힌트가 있네요.


왠지 모르겠지만 일단 2를 PUSH합니다.


그리고 LEA(MOV와 비슷한 명령어)를 하는데, ECX 레지스터에 ESP+A 위치의 값을 넣어줍니다.


현재 ESP는...



0019F98C네요.(스택포인터의 값은 실행마다 바뀝니다. 그때 항상 다르기때문에 체크하셔야 합니다.)


이 주소에 +A(10)을 해주면...


C는 12이므로, 22가 됩니다. 22는 16+6이므로,


0019F996이 되겠네요.


0019F996에 무슨값이 있나 봐야겠습니다.



끝에서부터 94 = 41 / 95 = 61(a) / 96 = 46 / 97 = 46


로 볼 수 있습니다. 즉, 0019F996 위치에는 46(='F')가 들어있습니다.


이는 저희가 입력한 문자열(AaFFFFF)에서 세번째 자리를 의미하겠네요.


아무튼 LEA명령어를 실행하면...



이렇게 주소값이 옮겨집니다. MOV는 값을 옮기지만 LEA는 주소값을 옮기는 것을 알 수 있습니다.


이 주소값은 ECX 레지스터로 이동합니다.


친절하게 저희가 입력한 문자열이 다 뜨네요.


다음 명령어는...



PUSH 406078 입니다.


4060XX 이 주소값의 영역은 바이너리 값이 들어있습니다. 바이너리 값은 올리디버그 좌측 하단에 있습니다.


볼까요?



00406078 위치에 35 가 있습니다. 35는 5이고 79는 'y'입니다.


저 헥사값 두자리가 1바이트입니다.(헥사값 1자리 = 4비트 => 0x0~0xF => 0b0000~0b1111)


PUSH 406078 명령어와 PUSH ECX 명령어를 실행했습니다.


PUSH 동작이므로 스택메모리를 봐야겠죠?




현재 스택 포인터(스택의 꼭대기)는 0019F984이고, 스택의 최상위 2개는 주소값이 있습니다.


맨 위의 주소는 유저가 입력한 문자열이 있는 스택메모리의 주소,


그 아래의 주소는 바이너리 값의 주소 입니다.


(참고로 스택 포인터는 스택을 쌓을수록 작아집니다. 스택은 아래에서 쌓는 것이 아니라 꼭대기에서 내려옵니다. 마치 종유석과 같습니다.)


왜 저 문자열을 주석으로 달아놨는지는 잘 모르겠습니다. 왜 1Byte 값만 가져오지 않을까요?


아무튼, 이 두 주소를 PUSH 한 다음, CALL 00401150 을 실행합니다.


이로써, PUSH 한 두 주소값은 함수의 파라미터라고 볼 수 있습니다.


대충 이런 함수겠네요.


func_00401150(addr& binary_addr, addr& user_input_addr)


이 함수는 그냥 넘깁시다. F8을 눌러서 Step Over 를 실행합니다.



함수 내부 동작에서 EAX 를 1로 만들었고, ECX 를 1로 만들었습니다.



다음 명령어를 보니, 또 다시 실패 창을 띄우는 명령어가 다가오네요.


일단 ADD ESP, 0C 를 합니다.



ESP 값이 0019F984 에서 C값이 더해진 0019F990 으로 바꼈습니다.


다음 명령어를 봅시다. TEST EAX, EAX 입니다.

TEST 명령어는 CMP 명령어와 다르게 AND 연산을 합니다.(CMP 명령어는 SUB연산입니다!)

즉 EAX, EAX 를 AND 연산을 하는데... 결과가 0이면 ZF가 1로 set 될 것입니다.

JNZ는 Jump if Not Zero, 즉 연산의 결과 값이 0이 아니면, 다시 말해 ZF가 0이면 점프를 합니다.

안타깝게도 EAX 가 1이므로 EAX끼리 AND를 시키면 1이 되고, 이는 ZF가 0으로 유지됩니다.

그러면 JNZ 명령어로 실패 창으로 가게 됩니다.

실행해볼게요.


안타깝게도 실패했습니다.

하지만 리버싱의 느낌으로, 왠지 5y가 들어가야 할 것 같습니다.

406078 부분에 5y 앞뒤로 NULL 값으로 도배가 되어 있기 때문에, 3번째 자리와 4번째 자리에 5y를 넣어야 할 것 같습니다.

그러면 00401135 함수는 이 두 문자열을 검사하는 함수일 것 같네요.

함수 결과가 EAX = 1로 셋 되었는데, 만약 입력값과 5y가 같으면 EAX를 0으로 클리어하고 ZF를 1로 셋 할 것 같습니다.

Ctrl + F2 를 눌러 재시작을 하고, Xa5yXXX...를 입력해봅시다.


이번엔 Aa5yFFFF를 입력했습니다.


네 성공적으로 4010CD(실패 창 이동) 을 넘었습니다.

이로써 두번째 자리는 a / 세번째 자리는 5 / 네번째 자리는 y 가 와야 함을 알 수 있습니다.

이번엔 PUSH EBX, PUSH ESI 동작이 있네요. 두개 다 실행하겠습니다.


두개 전부 스택에 올라갔습니다. (EBX = 0x1, ESI = 0xF0772)

다음 명령어를 볼까요?


4060XX 영역은 바이너리 영역이므로, 이 40606C 에서 NULL 까지 문자열을 봐야겠습니다.

일단 ESI 에는 40606C라는 값이 들어갈 것입니다.


(바뀐 ESI, 친절하게 문자열을 알려줍니다.)


0040606C(=0x52) 부터 NULL 이전까지의 문자열 ("R3versing") 을 확인할 수 있습니다.

다음 명령어는...


LEA 명령어입니다. 주소값을 옮기는 명령어입니다.

ESP+10의 위치네요. 현재 ESP의 값은


0019F6E8 입니다. 여기에 +10을 하면

0019F6F8 입니다. 명령어를 실행해 볼게요.


EAX 레지스터에 0019F6F8 주소가 옮겨졌습니다. 주석으로 ASCII "FFFF"라고 되어있네요.

왠지...FFFF랑 R3versing 이랑 같아야 할 것 같습니다.

확인해 볼게요.

다음 명령어는


하나의 Routine 으로 묶여있습니다.

=====================================================================
처음에 EAX 의 주소값(EAX 레지스터에 담겨져 있는 주소값) 위치의 값을 DL(EDX 레지스터의 하위 8비트) 에 옮깁니다.

그리고 ESI 의 주소값 위치의 값을 BL(EBX 레지스터의 하위 8비트) 에 옮깁니다.

그리고 DL의 값은 다시 CL로 옮기고, BL과 DL을 비교합니다.

CMP 명령어 이기 때문에, DL과 BL이 같으면 결과 값이 0이 될 것이고, 그러면 ZF는 1이 될 것입니다.

만약 두 값이 같지 않으면(ZF가 0이면) 00401102 로 점프합니다. (00401102 위치에는 EAX 를 -1로 만들어서 실패하게 만드는 아주 무서운 과정이 들어있습니다.)

위의 과정을 통과했으면, CL을 TEST 연산 합니다.

이는 CL이 0인지 아닌지 검사합니다. 이 말은, DL 이 NULL인지를 검사하는 것입니다. 다시 말해서 값의 여부를 판단, 즉 문자열의 끝인지를 판단 후 저 Routine 을 빠져나갑니다.

이로써 저 Routine 은 반복문이고, TEST CL, CL 은 break 조건임을 알 수 있습니다.

그 다음, EAX+1(1바이트를 의미합니다.) 위치의 값을 DL에 넣고, ESI+1 위치의 값을 BL에 넣고, 또 다시 비교를 합니다.

다르면? 00401102(실패 창) 로 점프합니다.

그리고 EAX와 ESI 에 2씩 더해줍니다. 이유는 문자(character)를 검사했는데, 2개를 검사했기 때문입니다.

2바이트를 더해주어야 그다음에 또 다시 2바이트를 검사할 수 있습니다.

그리고 TEST CL, CL 을 통해 문자열의 끝을 검사합니다.

CL 이 0이 아니면, 다시 말해 끝이 아니면 루틴의 처음(004010DA)으로 돌아갑니다.
=====================================================================

위의 과정의 루틴입니다. 당연히 실패 창으로 넘어갑니다.

왜냐하면 저희가 입력한 문자열 FFFFF는 R3versing 과 다르기 때문입니다.

이로써, a5y 다음에는 R3versing 을 입력해야 함을 알 수 있습니다.

그래도 실행은 해볼게요.


실패 창으로 가기 직전입니다.


레지스터 창입니다.

DL에는 46(='F')이 들어있고, BL에는 52(='R')가 들어있고, CL에는 DL과 같이 46이 들어있습니다.

46은 52와 다르기 때문에, JNZ 조건으로 실패 창으로 갑니다.

그러면 Ctrl + F2 를 누르고 재시작을 한 후, 이번에는


Aa5yR3versing 을 입력해보겠습니다.


해당 루틴을 5번 돈 후, 무사히 실패없이 통과했습니다.

다음 명령어는 XOR EAX, EAX 입니다.

리버싱에서 XOR EAX, EAX 는 EAX = 0 으로 만들겠다는 의미입니다.

같은 값을 Exclusive OR 하게 되면 모든 비트가 같기 때문에 전부 0이 되기 때문입니다.


예상대로 EAX가 0이 됬습니다.


다음 명령어는 JMP 00401107입니다.



EAX 를 -1로 만들어버리는 무서운 과정이 생략됬군요.


참고로 SBB는 캐리플래그도 연산에 포함시킵니다.


SUB 가 dest = dest - src 라면


SBB 는 dest = dest - (src - carry flag) 입니다.


아무튼 생략되었습니다. 이유는 아래에서 말하겠습니다.


바로 POP ESI, POP EBX를 해줍니다.



ESI에는 002D0094 라는 값이 들어갔고, EBX에는 00000001 값이 들어갔습니다.


TEST EAX, EAX 를 해줍니다.


그 아래에는



JNZ (Jump if Not Zero) 명령어가 있습니다.


이 뜻은, ZF가 0이면, 즉 EAX 가 0이 아니면 00401135(실패 창)으로 갑니다.



ZF가 1이네요.  실패하지 않습니다.


만약 SBB 과정을 거치게 되면, 이전에 TEST CL, CL과정에서 ZF가 1로 셋 되지 않고 ZF가 0으로 유지되기 때문에 실패합니다.


그 다음 명령어는



0x45(='E') 와 ESP+4위치의 값과 비교하는 것입니다.


현재 ESP는



0019F990입니다.


여기에 4를 더하면 0019F994입니다.



0x41(='A')입니다.


다르네요. A는 저희가 첫번째 자리에 입력한 문자입니다.


즉, 마지막으로 첫번째 자리에 0x45, 문자 'E'를 입력해야 함을 알아냈습니다.



실행시키면 역시 실패 창으로 갑니다.


다시 재시작 한 후, 이번에는 답으로 추정되는 Ea5yR3versing 을 입력해보겠습니다.



위의 과정을 전부 거친 후 문자열을 검사하고. 성공적으로 정답 창으로 왔습니다.


프로그램은 MessageBoxA에 정답이라는 것을 알려준 후 EndDialog를 통해 대화상자를 종료할 것으로 추측할 수 있습니다.



맞췄습니다.


정답은...


Ea5yR3versing


이었습니다.


영어로 EaSyREversing 이네요 ㅎㅎㅎ 리버싱 쉽대요


-------------------------------------------------------------------------------------------------------------------------------------------------------------


파일명 부터가 Easy_CrackMe.exe 여서 그런지 리버싱하는데 나름 쉬웠습니다.


처음으로 자력으로 해결한 프로그램이어서 더더욱 자세하게 설명한 것 같네요.


해결 못하신 분들은 제가 한 것처럼 따라서 해보시면 될 것 같습니다.


감사합니다.


>>> Reversing.kr


>>> Easy_CrackMe



'보안 & 모의해킹 > 리버싱' 카테고리의 다른 글

[Reversing.kr] - 3. Easy UnpackMe  (0) 2018.07.12
Posted by NDC :

* 윈도우 HDD 복구 파티션 삭제하기 *




윈도우 내에서 HDD의 복구 파티션을 삭제하는 방법을 알아보겠습니다.



참고 - CMD의 diskpart 명령어 : http://n1094.tistory.com/23?category=729401



보통 디스크 파티션 관리는 


내 PC  우클릭 [관리] 선택 → 디스크 관리


로 들어가서 할 수 있습니다.





저기 빨간색 네모친 부분을 들어가시면



이런 이미지를 보실 수 있습니다.


위의 이미지는 제가 임시로 상황을 만들어 놓은 것입니다... 재연을 위해서!




보통 복구 파티션은 저렇게 작은 용량(약 480MB정도의 크기, 위 이미지는 예시입니다!)을 가지고 있습니다. 


다른 파티션들과는 달리, 저 부분은 우클릭을 할 경우 도움말(H) 항목만 보여집니다.


이 파티션을 어떻게 지워야 할까요?


diskpart 명령어 사용하기


1. Win 키 + R 로 실행창을 연 후, diskpart 를 입력합니다. 혹은, cmd 창에서 diskpart 라고 입력하셔도 됩니다.





2. diskpart 콘솔창을 열었다면, 아래와 같은 화면을 보실 수 있습니다.





3. list disk 명령어를 통해 현재 컴퓨터가 인식하고 있는 디스크 목록을 봅니다.





4. sel disk 0 명령어를 통해 우리가 삭제해야 하는 파티션의 디스크를 선택(select) 해줍니다.





5. 해당 디스크의 내부에 구성되어져 있는 partition 을 살펴봅니다. list partition 명령어를 사용합니다.





6. 저희가 삭제해야하는 파티션이 보입니다. sel partition 2 명령어로 해당 파티션을 선택해줍니다.





7. 파티션을 선택하셨으면, delete partition override 명령어를 통해 해당 파티션을 삭제합니다.





8. 파티션을 삭제했다는 문구가 나오면, list partition 으로 해당 파티션이 잘 삭제되었나 봅니다.





해당 파티션이 출력되지 않음으로써, 우리는 우리가 삭제해야 하는 파티션을 잘 삭제했음을 알 수 있습니다.


마지막으로 요약 하겠습니다.



1. Win 키 + R 로 실행 창을 띄운 후, diskpart 입력 후 확인 혹은 cmd 창에서 diskpart 명령어 입력


2. list disk 로 해당 파티션의 디스크 확인


3. sel disk (번호) 로 해당 파티션의 디스크 선택


4. list partition 으로 해당 파티션 확인


5. sel partition (번호) 로 해당 파티션 선택


6. delete partition override 로 해당 파티션 삭제


7. list partition 으로 해당 파티션이 잘 삭제되었나 확인




이상으로 디스크 관리 화면에서 삭제할 수 없는 파티션을 삭제하는 법을 알아보았습니다.


복구 파티션 외에도 디스크 관리 화면에서 삭제할 수 없는 파티션이나 디스크는 위에서 살펴본 diskpart 콘솔창에서 삭제할 수 있습니다.



Posted by NDC :

 *** MySQl 기본적인 명령어 *** 


데이터베이스를 관리해주는 DataBase Management System, 줄여서 DBMS 라고 합니다.


이 DBMS 도 C 컴파일러(dev-C, gcc 등등) 처럼 여러 종류가 있는데요.


Oracle 사의 DBMS, MS 사의 MySQL, 그리고 MySQL 에서 분파(?)한 MariaDB 등등 SQL 을 사용할 수 있는 DBMS 시스템에도 종류가 있습니다.


이 글은 MS 사의 MySQL 을 기준으로 하겠습니다.


---------------------------------------------------------------------------------------------------------------------------------------------------------



1. Database 선택하기


Database 가 여러 개가 있을 경우, 쿼리문을 어느 DB에 사용할 것인가?


>>> use (db_name)

* 이후 발생하는 쿼리문들은 모두 db_name 의 데이터베이스에서 실행됩니다.




2. (table_name) 의 모든 정보 보기


(table_name) 테이블에 있는 모든 정보를 보고 싶다?


>>> select * from (table_name)




3. 2개 이상의 테이블을 한 번에 보기


(table_name1) 과 (table_name2) 의 이루어 질 수 있는 모든 경우의 수를 보고 싶다?


>>> select * from (table_name1), (table_name2)

* 단순히 콤마를 통해 두 테이블을 연결할 경우, 두 테이블에서 나올 수 있는 모든 경우의 row가 발생한다.

즉, table_name1 의 row 개수가 100개, table_name2 의 row 개수가 20개라면

위의 쿼리문으로 나오는 row 의 개수는 100 * 20 = 2000개 가 나온다.




4. 중복된 정보를 제거한 후 보기


특정 칼럼에서 중복된 값들을 제거한 후 하나씩 만을 보고 싶다?


>>> select distinct (column_name) from (table_name)

* 반복적인 1, 2, 3 의 값으로 되어있는 column 에 distinct 를 붙인다면

단 3개의 row 가 나온다. (1, 2, 3)




5. 상위 n개의 row 만 보기


단순하게 위에서 n개의 row만을 보고 싶다?


>>> select top (n) (column_name) from (table_name)




6. 두 개의 칼럼을 합쳐서, 하나의 칼럼으로 따로 보기


테이블을 한 번에 보는 것이 아닌, 두 개의 칼럼을 합쳐서 따로 새로운 칼럼으로 보고 싶다?


>>> select (column_name1) + (column_name2) from (table_name)

* 위의 쿼리문을 실행하면, (열 이름 없음) 이라는 새로운 column 에서 두 column 을 그대로 합친 결과를 볼 수 있습니다.

만약 (열 이름 없음) column 에 이름을 지어주고 싶다면


>>> select (column_name1) + (column_name2) as (new_column_name) from (table_name)

위처럼 as 문을 사용하면 가능합니다.


>>> as 는 "Rename" 기능을 가지고 있습니다. 

from MyTable as MT 라고 한다면, 이후에 MyTable.column1 대신 MT.column1 이렇게 접근할 수 있습니다.




7. 특정 column 에 대하여 정렬된 상태로 보기


칼럼이 여러 개가 있을 경우, 어떤 특정 칼럼에 대해 정렬된 상태로 보고 싶다?


>>> select (column_name) from (table_name) order by (wanted_column_name)

* 위의 쿼리문을 실행하면, (열 이름 없음) 이라는 새로운 column 에서 두 column 을 그대로 합친 결과를 볼 수 있습니다.

그런데 이 정렬의 기준이 될 column 은 2개 이상도 가능합니다.


>>> select (column_name) from (table_name) order by (wanted_column_name1), (wanted_column_name2)

* 이 쿼리문을 실행하면, (wanted_column_name1) 과 (wanted_column_name2) 에 맞춰져서 정렬된 상태로 테이블의 row 들을 보여줍니다.

정렬의 기준은 알파벳 순서 (ex. a~ ), 작은 숫자 (ex. 0~ ) 순서입니다.



---------------------------------------------------------------------------------------------------------------------------------------------------------


이후에 더 추가할 내용이 있다면 추가하도록 하겠습니다.

SQL 쿼리문에 들어가는 키워드를 중심적으로 봐주시면 될 것 같습니다.

(ex. 정렬이 필요하다? -> order by,   상위 n개의 row를 보고싶다? -> top (n) )


Posted by NDC :

* CMD 의 diskpart 명령어 *


내 PC 우클릭 -> 관리 -> 디스크 관리 에 보면 파티션을 삭제해야 하는 경우가 있다.


> diskpart

disk > partition 순서임


> listdisk


> select disk 0 또는 select disk 1 


이런식으로 디스크를 선택 -> 이는 내컴퓨터>관리>디스크관리 에서 확인가능

디스크를 선택하면?


> list partition


해당 선택된 디스크에 있는 파티션들이 나열되어서 보여짐

파티션 삭제는?


선택 -> 삭제


ex.

select partition 4

delete partition override 


이러면 4번 파티션이 삭제됨.

Posted by NDC :

* HTTP 에러 정리 *


가장 많이 볼 수 있는 것들이 404 Not found나 403 Forbidden 등이 있습니다. 이들은 서버에서 보내는 사용자의 요구에 대한 응답입니다. 


이러한 것들은 HTTP/1.0의 STATUS CODE라고 합니다. 즉, 이들 메시지만 잘 해독해도 많은 도움이 됩니다. 아래는 그 메시지의 설명입니다.


code : 200


reason field : OK 

의미 : 클라이언트의 request가 성공적으로 수행됐다. request처리결과로 클라이언트에게 전달되는 정보는 사용된 method에 따라서 달라진다.


reason field : GET

의미 : request가 지정한 자원이 response메세지로 전달 된다. 


reason field : HEAD

의미 : response메세지에는 요청된 자원에 관한 정보를 나타내는 header만이 포함된다. 


reason field : POST

의미 : 지정된 동작의 수행결과를 포함하거나 결과를 설명하는 엔터티가 전달된다. 



code : 201


reason field : Created

의미 : request가 처리되었고 그 결과로 새로운 자원이 생성되었다. 생성된 새로운 자원을 나타내는 URI 값이 response메시지로 전달된다. 서버가 이와 같은 status code(상태코드)를 클라이언트에게 전달하기 위해서는 새로운 자원을 먼저 생성시켜야 한다. response메시지를 전달 할때까지 새로운 자원이 생성되지 못하면 status code 202(Accepted)를 보내야 한다. POST method만이 서버에 새로운 자원을 생성시킬 수 있다. 


code : 202


reason field : Accepted

의미 : request가 수락되었으나 response메시지를 전달할 때까지 그 프로세싱이 완료되지 못했으며 또한 언제까지 request의 수행결과를 사용자가 볼 수 있을지를 확실히 판단할 수 없다. 이와 같은 status code는 request가 수락된 것(accepted)만을 나타낼뿐 궁극적으로 그 request가 처리될 것이라는 보장 할 수 없을 때 사용된다. status code 202는 Web 브라우저와 같이 서버의 처리결과를 전달받을 때까지 계속 기다리게 되는 클라이언트를 위한 것은 아니다. WEb브라우저와는 다른 일종의 batch프로세서(하루에 한번정도 실행되는)의 request를 서버가 받아들일 수 있도록 하기위한 것이다. 


code : 204


reason field : No Content

의미 : 서버가 request를 처리했지만 클라이언트에게 전달할 새로운 정보가 없다. 이 status code를 전달받는 Web브라우저는 현재 디스플레이 중인 내용을 변경시키지 않아야 한다. 이 code를 정의한 주된 목적은 현재 디스플레이 중인 문서의 내용을 변경시키지 않으면서 CGI스크립트 등에 입력을 전달할 수 있도록 하기 위해서이다. 


code : 300


reason field : Multiple

의미 : HTTP/1.0을 사용하는 경우에는 이 code가 직접적으로 사용되지는 않는다. 다만, 3xx클래스에 속하는 status code의 디폴트값으로 사용된다. 그 의미는 301, 302, 304만이 HTTP/1.0에 정의되어 있으므로 그 외의 status code값을 전달받는 경우에는 300으로 간주한다는 의미가 되는 것이다. 


code :301


reason field : Moved

의미 : 요청된 자원의 URI값이 완전히 변경되었으므로 앞으로는 새로운 URI값을 사용하여야 한다. 새로운 URI값은 Location(위치)헤더를 통해서 클라이언트에게 전달된다. 또한 HEAD method를 제외한 모든 경우에 response메시지의 entity(실재) body를 통해서 새로운 URI의 하이퍼링크를 포함 하는 짧은 메시지를 전달해 주어야 한다. Web브라우저는 POST method를 사용한 request의 결과로 301 status code를 전달받는 경우에는 자동으로 새로운 URI에 접속해서는 안된다. 반드시, 사용자의확인을 거쳐야 한다. 


code :302


reason field : Moved

의미 : 요청된 자원의 URI값이 임시로 변경되었다. 따라서 추후 Temporarily(임시폴더)에도 현재의 URI값을 계속 사용하여야 한다. 새로운 URI값은 Location헤더를 통해서 클라이언트에게 전달된다. 또, HEAD method를 제외한 모든 경우에 response메시지의 entity body를 통해서 새로운 URI의 하이퍼링크를 포함하는 짧은 메시지를 전달해 주어야 한다. Web브라우저는 POST method를 사용한 response의 결과로 302 status code를 전달받는 경우에는 자동으로 새로운 URI에 접속을 해서는 안된다. 반드시 사용자의 확인을 거쳐야 한다. 


code : 304


reason field : Not

의미 : conditional GET method가 사용된 경우에 전달된다. Modified request를 처리한 결과 If-Modified-Since헤더에 지정된 날짜/시간 이래로 지정된 문서가 변경된 사실이 없는 경우 서버는 이 status code로 응답해야 한다. 이때, entity body는 전송되지 않는다. reseponse메시지로 전달되는 헤더들은 주로 cache와 관련된 정보를 포함하게 된다. cache manager(대개의 경우는 Web브라우저 자체에 그 기능이 포함된다)는 304 response에 포함된 헤더의 값을 cache된 entity들에 반영할 수 있도록 하여야 한다. 


code : 400


reason field : Bad Request

의미 : request메시지의 syntax(체계, 배열)가 잘못되어서 서버가 request를 처리할 수 없다. 재접속을 하는 경우에 클라이언트는 반드시 올바른 request메시지를 사용해야 한다. 


code : 401


reason field : Unauthorized 

의미 : request가 user quthentication을 필요로 한다는 것을 클라이언트에게 알려주기 위해서 사용된다. WWW-Authenticate(인증하다, 증명하다)헤더를 통해서 요청된 자원에 적용되는 challenge를 전달한다. 401 response를 받은 클라이언트는 적절한 Authorization credentials(위임장)를 포함하는 Authorization헤더와 함께 다시 request메시지를 전송한다. request메시지에 그와 같은 Authorization credentials이 포함된 경우에 401 status code가 전달되면 user authentication이 실패한 것을 나타낸다. 


code : 403


reason field : Forbidden

의미 : 서버가 request의 처리를 거절하는 것을 나타낸다. 이와 같은 응답을 받은 경우에는


동일한 request를 반복하지 말아야 한다. 왜냐하면 무조건 request가 거절되는 것이기 때문이다. 403 status code는 request를 거절하는 이유를 명시적으로 밝히고 싶지 않거나 적절한 status code가 없을때 사용된다. 


code : 404


reason field : Not Found

의미 : Request-URI에 해당하는 자원을 찾을 수 없을 경우에 사용된다.


그런 상태가 일시적인 것인지 아니면 언제나 그렇게 되는지를 나타내는 어떤 정보도 전달되지 않는다. 이런 상태를 클라이언트에게 알리고 싶지 않은 경우에는 403 code를 대신 사용해도 된다. 


code : 500


reason field : Interna

의미 : 서버프로그램에서 예기치 않은 오류가 발생하여서 request Srever Error 를 처리할 수 없다. 


code : 501


reason field : Not

의미 : request를 처리하기 위해서는 필요한 기능을 서버가 갖추고 Implemented(충족시키다)있지 못하다. 


code : 502


reason field : Bad

의미 : gateway나 proxy로 동작하는 서버가 사용하는 것으로 자신 Gateway의 위쪽에 있는 서버로 부터 잘못된 response메시지를 전송 받았다는 것을 나타낸다. 


code : 503


reason field : Service

의미 : 과부하나 서버 maintenance(유지, 보존) 때문에 서버가 잠시동안 request Unavailable(요청불가능)를 처리해 줄 수 없는 상태에 있다.



Posted by NDC :

상 관리자 권한으로 실행하기 *



1. exe 파일 우클릭 

2. > 속성 

3. > 호환성 

4. > 하단에 '관리자 권한으로 이 프로그램 실행' 체크

5. > 적용 

6. > 확인

Posted by NDC :

 * 마우스 우클릭에 기능 추가하기 *


나의 상황에서... 


어떤 *.exe, *.dll 파일을 Olly-dbg 로 한번에 열고 싶을 때가 있었다. 

그래서 마우스 우클릭에 기능을 추가해 보았다. 



1. Win키 + R > regedit.exe 입력 -> registry 편집기 실행된다.


여기서 컴퓨터 > HKEY_CLASSES_ROOT > * > shell 들어간다.


[shell] 우클릭 > 새로 만들기 > 키 선택


[새 키 #1] 라는 폴더가 하나 생성됨.


여기서 이름을 바꾼다. 이 이름은 이제 우클릭하면 보여질 이름이다.

나는 [Open with Olly-Dbg] 라고 하겠다.


그럼 [Open with Olly-Dbg] 를 또다시 우클릭, 새로 만들기 > 키 선택


또다시 새 키가 하나 생성된다.


이 키(폴더)의 이름을 [command] 라고 수정하자.


[command] 키(폴더)를 더블클릭하면 옆에 (기본값)이라는 이름의 REG_SZ 가 하나 보인다.


일단 regedit은 여기까지 하고, exe 실행파일의 경로를 따야 한다.


나의 OllyDbg.exe 의 경로를 복사하자.

(복사하는 법:exe 파일 Shift + 우클릭 > 경로로 복사(A) 클릭 > 클립보드에 임시로 경로복사됨.)


경로가 복사되었으면, 다시 regedit 의 ... > command > (기본값) 으로 와서,


(기본값)을 더블클릭 한다.


그럼 값 데이터(V): 라는 항목을 볼 수 있다.


여기에 Ctrl + V 로 클립보드의 항목(경로)을 붙여넣기 하자.


"D:\Files\...\OLLYDBG.EXE" 라고 나올 것이다.(큰따옴표가 있어야한다.)


그 뒤에 "에 커서를 두고 Space-Bar 로 공백을 하나 만든 후, 그 뒤에


"%1"


라고 입력하자.(큰따옴표 포함임)

그리고 확인을 누르고 regedit 을 종료하자.


그러면 당신이 어떤 프로그램을 우클릭했을 때, Open with Olly-Dbg 라는 항목이 생기고,


그 항목을 누르면 그 프로그램을 Olly-dbg 로 열 수 있다.

Posted by NDC :