난독화 C코드 콘테스트 2006.sykes 2.c에 대해 설명해 주세요.
이 C 프로그램은 어떻게 작동합니까?
main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}
합니다(「」에서 테스트 완료).gcc 4.6.3
이치노 ★★★★★★★★★★★★★★★★★★★★:
!! !!!!!! !! !!!!!! !! !!!!!!
!! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !!
!! !!!!!! !! !! !! !! !! !!!!!!
!! !! !! !! !! !! !!
!! !! !! !! !! !! !!
!! !!!!!! !! !! !! !!!!!!
출처: sykes2 - 한 줄의 클럭, sykes2 작성자 힌트
.디폴트당 컴파일 경고는 없습니다.「 」와 컴파일.-Wall
다음 경고가 발생합니다.
sykes2.c:1:1: warning: return type defaults to ‘int’ [-Wreturn-type]
sykes2.c: In function ‘main’:
sykes2.c:1:14: warning: value computed is not used [-Wunused-value]
sykes2.c:1:1: warning: implicit declaration of function ‘putchar’ [-Wimplicit-function-declaration]
sykes2.c:1:1: warning: suggest parentheses around arithmetic in operand of ‘|’ [-Wparentheses]
sykes2.c:1:1: warning: suggest parentheses around arithmetic in operand of ‘|’ [-Wparentheses]
sykes2.c:1:1: warning: control reaches end of non-void function [-Wreturn-type]
해독하자.
들여쓰기:
main(_) {
_^448 && main(-~_);
putchar(--_%64
? 32 | -~7[__TIME__-_/8%8][">'txiZ^(~z?"-48] >> ";;;====~$::199"[_*2&8|_/64]/(_&2?1:8)%8&1
: 10);
}
이 문제를 해결하기 위한 변수 소개:
main(int i) {
if(i^448)
main(-~i);
if(--i % 64) {
char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
putchar(32 | (b & 1));
} else {
putchar(10); // newline
}
}
:-~i == i+1
둘만의 관계 때문에. 때문에 는 ★★★★★★★★★★★★★★★★★★★★」
main(int i) {
if(i != 448)
main(i+1);
i--;
if(i % 64 == 0) {
putchar('\n');
} else {
char a = -~7[__TIME__-i/8%8][">'txiZ^(~z?"-48];
char b = a >> ";;;====~$::199"[i*2&8|i/64]/(i&2?1:8)%8;
putchar(32 | (b & 1));
}
}
이제 와 같은 것을 주의하고 를 적용합니다.-~ == 1+
시시시:
main(int i) {
if(i != 448)
main(i+1);
i--;
if(i % 64 == 0) {
putchar('\n');
} else {
char a = (">'txiZ^(~z?"-48)[(__TIME__-i/8%8)[7]] + 1;
char b = a >> ";;;====~$::199"[(i*2&8)|i/64]/(i&2?1:8)%8;
putchar(32 | (b & 1));
}
}
재귀를 루프로 변환하고 조금 더 심플하게 슬쩍 들어갑니다.
// please don't pass any command-line arguments
main() {
int i;
for(i=447; i>=0; i--) {
if(i % 64 == 0) {
putchar('\n');
} else {
char t = __TIME__[7 - i/8%8];
char a = ">'txiZ^(~z?"[t - 48] + 1;
int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
if((i & 2) == 0)
shift /= 8;
shift = shift % 8;
char b = a >> shift;
putchar(32 | (b & 1));
}
}
}
1번으로 하다64번입니다. 이외의 경우는,) 문자 33(a 「스페이스」)을합니다.!
번째 테이블 「 」 「 」 「 。">'txiZ^(~z?"
는 각로, 두 표는 10비트맵으로 구성되어 있습니다.";;;====~$::199"
는 비트맵에서 는 비트맵에서 표시할 적절한 비트를 선택합니다.
두 번째 테이블
두 번째인 '두 번째 표부터 살펴볼까요?int shift = ";;;====~$::199"[(i*2&8) | (i/64)];
i/64
와 행번호(6~0)입니다.i*2&8
는 8 iff 8 ifff 8 입니다.i
78.4, 5, 6, 는7 mod 8 입니다.
if((i & 2) == 0) shift /= 8; shift = shift % 8
는, 자리(「」의 경우) 중 합니다.i%8
) (= 0,1,4,5)의 경우 8진수(예: 8진수)i%8
= (2,3,6,7)시프트 테이블은 다음과 같습니다.
row col val
6 6-7 0
6 4-5 0
6 2-3 5
6 0-1 7
5 6-7 1
5 4-5 7
5 2-3 5
5 0-1 7
4 6-7 1
4 4-5 7
4 2-3 5
4 0-1 7
3 6-7 1
3 4-5 6
3 2-3 5
3 0-1 7
2 6-7 2
2 4-5 7
2 2-3 3
2 0-1 7
1 6-7 2
1 4-5 7
1 2-3 3
1 0-1 7
0 6-7 4
0 4-5 4
0 2-3 3
0 0-1 7
또는 표 형식으로
00005577
11775577
11775577
11665577
22773377
22773377
44443377
작성자는 처음 2개의 테이블엔트리(슬리키!)에 늘 터미네이터를 사용했습니다.
은, 「7」의「7」의 「7」의 표시 되고 있습니다.7
스스 스스 스스 스 스 스 스 스님따라서 첫 번째 테이블의 엔트리는 켜지는 세그먼트를 정의해야 합니다.
첫 번째 테이블
__TIME__
는 프리프로세서에 의해 정의되는 특수한 매크로입니다.다음 형식으로 프리프로세서가 실행된 시간을 포함하는 문자열 상수로 확장됩니다."HH:MM:SS"
확인합니다. 정확히 8글자가 포함되어 있는 것을 확인합니다. ~ 9의 값은 ~, 0 ~9 의 ASCII 값은 48 ~57 입니다.:
에는 ASCII값 .은 한.__TIME__
.
7 - i/8%8
is of of of of of of of of of of of of of의 가 됩니다.__TIME__
되고 있는 것(「출발중」)7-
하고 있기 한 것입니다.i
이렇게 해서t
의 특징입니다.__TIME__
력중입입니니다
a
다음 2진수로 .t
:
0 00111111
1 00101000
2 01110101
3 01111001
4 01101010
5 01011011
6 01011111
7 00101001
8 01111111
9 01111011
: 01000000
각 숫자는 7 세그먼트 디스플레이에 점등하는 세그먼트를 나타내는 비트맵입니다.문자는 모두 7비트 ASCII이므로 하이비트는 항상 클리어 됩니다.따라서,7
항상 공백으로 인쇄됩니다.는 이렇게 있어요.7
s는 공백입니다.
000055
11 55
11 55
116655
22 33
22 33
444433
예를 예를 들면요.4
01101010
1,, 5 (비트 1, 3, 5, 6 세트),
----!!--
!!--!!--
!!--!!--
!!!!!!--
----!!--
----!!--
----!!--
코드를 제대로 이해하고 있음을 보여주기 위해 다음 표에서 출력을 조금 조정해 보겠습니다.
00
11 55
11 55
66
22 33
22 33
44
은 음음음음음음음음음 as as as as as as as as라고 되어 있습니다."?;;?==? '::799\x07"
몇 을 주지 64자를 더하게 됩니다"?{{?}}?gg::799G"
(8번째 캐릭터는 사용하지 않기 때문에 실제로 원하는 대로 만들 수 있습니다.)코드로 방법:
main(_){_^448&&main(-~_);putchar(--_%64?32|-~7[__TIME__-_/8%8][">'txiZ^(~z?"-48]>>"?{{?}}?gg::799G"[_*2&8|_/64]/(_&2?1:8)%8&1:10);}
얻을 수 있다
!! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !! !! !! !! !! !! !!
!! !! !!
예상대로입니다.원작만큼 단단하지 않은 표로 만든 것도 이 책의 표가 왜 쓰였는지를 알 수 있다.
읽기 쉽도록 포맷합니다.
main(_){
_^448&&main(-~_);
putchar((--_%64) ? (32|-(~7[__TIME__-_/8%8])[">'txiZ^(~z?"-48]>>(";;;====~$::199")[_*2&8|_/64]/(_&2?1:8)%8&1):10);
}
인수으로 _(argc)입니다.1
main()
자신을 해, 「이러다」의 합니다.-(~_)
비트 of (부정 비트 단위 NOT)_
, 448 재귀 _^448 == 0
를 참조해 주세요.
로 된 가로줄 , 7개, 세로줄 7개, 세로줄 64개, 가로줄 7개, 세로줄 7개, 세로줄 , 세로줄 7개, 세로줄 3개, 세로줄 64개.448/64 == 7
더 깨끗하게 다시 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 맞다.
main(int argc) {
if (argc^448) main(-(~argc));
if (argc % 64) {
putchar((32|-(~7[__TIME__-argc/8%8])[">'txiZ^(~z?"-48]>>(";;;====~$::199")[argc*2&8|argc/64]/(argc&2?1:8)%8&1));
} else putchar('\n');
}
그럼 이제 ㅇㅇㅇㄹㄹㄹㄹ,32
ASCII ascii진진10 진진진진 ascii'!'(33은 '!')를★★★★★★★★▼&1
'아주머니'가운데 있는 블롭에 초점을 맞추겠습니다.
-(~(7[__TIME__-argc/8%8][">'txiZ^(~z?"-48]) >>
(";;;====~$::199"[argc*2&8|argc/64]) / (argc&2?1:8) % 8
또 다른 포스터에도 있듯이__TIME__
는 프로그램의 컴파일 시간이며 문자열이기 때문에 문자열 연산이 진행되며 배열 첨자가 양방향인 장점을 활용합니다.a [ b ]는 문자 배열의 b [a ]와 같습니다.
7[__TIME__ - (argc/8)%8]
8자 중에서 중 됩니다.__TIME__
후, 은 「 」, 「 」로 됩니다[">'txiZ^(~z?"-48]
(0 ~ 9 ~ ~ 48 ~57 。ASCII를 사용하다이 같은 문자 ASCII 코드 조작은 식을 통해 계속되며, 문자의 글리프 내 위치에 따라 ' 또는 '!'가 인쇄됩니다.
가능한 한 모듈로 산술의 해독을 해제하고 재귀를 제거했습니다
int pixelX, line, digit ;
for(line=6; line >= 0; line--){
for (digit =0; digit<8; digit++){
for(pixelX=7;pixelX > 0; pixelX--){
putchar(' '| 1 + ">'txiZ^(~z?"["12:34:56"[digit]-'0'] >>
(";;;====~$::199"[pixel*2 & 8 | line] / (pixelX&2 ? 1 : 8) ) % 8 & 1);
}
}
putchar('\n');
}
조금 더 확대:
int pixelX, line, digit, shift;
char shiftChar;
for(line=6; line >= 0; line--){
for (digit =0; digit<8; digit++){
for(pixelX=7;pixelX >= 0; pixelX--){
shiftChar = ";;;====~$::199"[pixelX*2 & 8 | line];
if (pixelX & 2)
shift = shiftChar & 7;
else
shift = shiftChar >> 3;
putchar(' '| (">'txiZ^(~z?"["12:34:56"[digit]-'0'] + 1) >> shift & 1 );
}
}
putchar('\n');
}
해결책에 , 른른른 adding adding adding adding adding adding adding adding adding adding-~x
x+1
~x
(0xffffffff-x)
. . . . 。(-1-x)
이므로 2s의 보완, 2s의 보완, 2s의 보완-~x
-(-1-x) = x+1
.
언급URL : https://stackoverflow.com/questions/15393441/obfuscated-c-code-contest-2006-please-explain-sykes2-c
'programing' 카테고리의 다른 글
java.util을 변환합니다.java.time 날짜로컬 날짜 (0) | 2022.06.04 |
---|---|
알려진 리소스 이름을 가진 리소스 ID를 가져오려면 어떻게 해야 합니까? (0) | 2022.06.04 |
[Vue.js] Vuex에서의 네임스페이스 (0) | 2022.06.04 |
C에서 _start()의 용도는 무엇입니까? (0) | 2022.06.04 |
Vue js - 특정 유형으로 프로펠러 정의 (0) | 2022.06.04 |