knowledge(stmate): BSC 기준자료 분석 — JDCODE·GRPCOD 코드 사전 · CSTA 표준시장단가 · STBSC 배포 묶음 · 제비율 44판 · SIX 암호 열쇠 복원

- ST_BSC 전부 해독(미해독 0) · 열쇠 식 SDECDX50.DLL · 암호 STmate.Cpm 0x5e34e8 평문 내장
- 기초단가 사전 9만여 코드(2026-09-01판) · 표준시장단가 ~5천 · 일위대가 구성 · 갱신 연 2회
- BDQTY·SYSINFO 열쇠도 확인(35 §7 · 37 미확인 닫음)
- 풀어낸 자료는 git 밖 tmp/bsc

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-14 18:22:24 +09:00
co-authored by Claude Opus 5.5
parent b9847c7db8
commit 22a3942f23
2 changed files with 162 additions and 0 deletions
@@ -124,3 +124,4 @@ REA 6.7.0 / Ghidra 12.1.4 / 기존 JDK 21.0.7. Ghidra는 LOCALAPPDATA/STMATE-REA
- 2026-11-14 38단계: [보고서 잔여 서식 정적 분석](38_보고서_잔여_작업자료_20261114/38_보고서_잔여_정적분석.md) — 엑셀판 = ST_P_XLS · 설계내역서 쪽 채움(LNP_CNT · 0x520e34 · 원본 3건 행 번호 일치) · 인쇄 영역 $A:$열·탭 색 · 0605 금회 = BOQ QTY2·T_AMT2 · 0615 견적·기준 = xAMT1·xAMT2 두 행 · 0695 회사분 0·도급분 DTP 참조 · 0651 시기금·구기금 = 고른 1·2 차수 T_AMT · 토개공·수자원 글 없음. 바이트 읽기만, 원본 실행 없음.
- 2026-11-14 37단계: [파일 입출력 잔여 정적 분석](37_파일입출력_잔여_작업자료_20261114/37_파일입출력_잔여_정적분석.md) — JDL TEXT = 탭 구분(검사기 고정폭 표는 죽은 고리 · 34 §17.9 바로잡음) · 단가 목록 7종·Main·Global.Ini 줄 규칙 · 세부 3종 열 이름 · 구버전 판 가리기·필드 대응(B→X 조건 = 단위 X) · 엑셀 역등록 구성 줄 PRPT·PRIN 뜻 · wM_JajeXLS = 재료비 수량집계표 내보내기만 · 그림 = COSTN I 코드 IFORM · SIZE = 그림 클래스 이름
- 2026-11-14 38b F5-31: [원가 줄 엑셀 수식](38_보고서_잔여_작업자료_20261114/38b_F5-31_원가줄수식.md) — 총괄 원가 줄 D·E 식 · H 숨은 메타(ST_P_XLS 0x4b8c6c) · I~P 보정·요율 칸 · 이윤 끝전 J·K·L 사슬 · 공사원가계산서 참조·비고·바로가기 · 산재·기타경비 겉 괄호 = 25 판 틀(0x494b53) · 원본 5건 1392칸 글·값 일치. Ghidra 읽기만, 원본 실행 없음.
- 2026-11-14 40단계: [BSC·STBSC 기준자료 분석](40_BSC_자료분석_20261114/40_BSC_자료분석.md) — ST_BSC 기준자료 전수 복호(미해독 0) · DBF 레코드 = Apollo/SIX 스트림 암호(열쇠 6: AABI1129 단가·코드 / OFOC0603 구성·BDQTY / INFO0301 SYSINFO / EQSN0301 / FORM6511 / SCOD0301 · 생성식 SDECDX50 0x10c03ba9·0x10c03cc2·0x10c03c9d · 글 상수 STmate.Cpm 0x5e34e8) · STBSC = 암호 ZIP(STmate123!@#) · JDCODE 사전(노무460·자재57,580·기계833·공종33,927)·GRPCOD 분류나무·CSTA 표준시장 4,961·일위대가 구성·JB 제비율 44판 · BDQTY 열쇠=OFOC0603·SYSINFO 암호 해소(35§7·37 미확인 닫음) · 자료 git 밖 tmp/bsc/. 원본 읽기만.
@@ -0,0 +1,161 @@
# 40. BSC·STBSC 기준자료 분석 (2026-11-14)
STMATE w 8.0 설치 `C:\경영정보(주)\System\ST_BSC\` 의 「기준자료」 전수 판독. 원본 읽기만 · 복사본 작업 · 풀어낸 자료 전체는 git 밖 `tmp/bsc/`.
## 0. 한눈 결과
- ST_BSC 의 기준자료 전부 풀림(미해독 0). 암호 종류 둘뿐: ① DBF 레코드 = Apollo/SIX 스트림 암호(열쇠 여섯), ② STBSC = 암호 ZIP(열쇠 하나).
- 과거 미해독이던 `SYSINFO.DBF`·`BDQTY.DBF 열쇠`·`JDCODE 칸 변환 표`(35 §7 F1-39 · 37 미확인)도 이 열쇠들로 모두 풀림.
## 1. 암호 푸는 법 (주소 근거)
### 1.1 DBF 레코드 암호 = Apollo/SIX 스트림 암호
- 머리 바이트 `0x06`(또는 `0xE6`)인 DBF 는 필드 표(헤더)는 평문, **레코드 본문만** 암호. `0x03` 은 평문.
- 복호식(자리별, 삭제표시 1바이트 빼고): `평문 = rol((암호 − k) & 0xFF, k & 7)`. `k` = 자리별 열쇠 바이트, 레코드마다 처음부터 다시 씀.
- 열쇠 흐름 = 8글자 암호에서 난수 생성(SIX 엔진 `SDECDX50.DLL`): 씨앗 `FUN_10c03cc2`(0x10c03cc2) → 되풀이 `FUN_10c03ba9`(0x10c03ba9, PRNG 상수 `0xDE6D·0x278D·0x2193`) · 7바이트 주기. **쓰는 열쇠 = 글 8바이트를 자기 자신으로 한 번 암호화한 값**(`FUN_10c03c9d` 0x10c03c9d: 버퍼에 글 복사 후 글로 암호화).
- 여는 쪽(메인 `STmate.Cpm`): COSTN·JDCODE 여는 함수 `0x45529c`·`0x4f10dc` 가 `IsEncrypted` 참이면 `SetPassword(글)`. 글 상수 여섯은 `0x5e34e8` 의 ShortString 배열에 평문으로 있음.
- 열쇠 여섯(접두어 = 표 종류):
| 열쇠 글 | 쓰는 표 |
|---|---|
| `AABI1129` | 단가·코드 계열 — `COST.ST`·`*.CSTA`·`JDCODE_*`·`GRPCOD_*` |
| `OFOC0603` | 구성표(일위대가·중기) — `XDET.ST`·프로젝트 `BDQTY.DBF` |
| `INFO0301` | 프로젝트 `SYSINFO.DBF` |
| `EQSN0301` | `EQSYNC.DBF`(장비 동기화 메타) |
| `FORM6511` | 수량산출서 서식 `FORM.DBF`(ST_BSC 밖) |
| `SCOD0301` | 조달 코드 계열(ST_BSC 밖) |
- 같은 꼴이 Apollo 래퍼 `SDE50.DLL`(`sx_Decrypt` 0x10005060 → 0x10005a20, 씨앗 0x10005b39)에도 있음 — 둘이 같은 알고리즘.
- **BDQTY 와 연결**: 기존 `tools/stmate-test/bdqty.py` 의 자리별 수동 변환표는 `OFOC0603` 열쇠 흐름과 일치(일위대가 구성표가 BDQTY 와 같은 표). 이제 「변환 표 미확보」(35 §7·37)가 해소 — 열쇠 = `OFOC0603`.
### 1.2 STBSC = 암호 ZIP
- `*.STBSC`·`*.STBK` = PKZIP 표준 암호 ZIP(엔트리 목록은 암호 없이 보임, 내용만 암호). 안의 엔트리 = `.ST`(위 1.1 의 DBF).
- ZIP 암호 = `STmate123!@#`(병합 모듈 `ST_U_Convert.CPM` 안 평문 문자열). 네 계열(실적단가·노임기계·일위대가·자재단가) 28개 모두 이 암호로 열림.
## 2. 파일 목록 (경로·크기·꼴·행 수·SHA256 앞 16)
전체 목록·전체 SHA256 = `tmp/bsc/inventory.json`.
### 2.1 코드·단가 대형표 (DBF `0x06`, 열쇠 AABI1129)
| 파일 | 크기 | 행 | 내용 | SHA256(앞16) |
|---|---|---|---|---|
| `JDCODE_L.BSC` | 156 KB | 460 | 노무 기초단가 코드 | d967e15b87c6a216 |
| `JDCODE_M.BSC` | 19.5 MB | 57,580 | 자재 기초단가 코드 | 69073533ba84c01b |
| `JDCODE_S.BSC` | 289 KB | 851 | 건설기계·일반경비 기초단가 코드 | 39a3e525399a842e |
| `JDCODE_X.BSC` | 283 KB | 833 | 기계경비 기초단가 코드 | 6304d8e0bb717efa |
| `JDCODE_Z.BSC` | 11.5 MB | 33,927 | 공종(토목·건축·설비) 일위대가·표준시장 코드 | decbd6a76ebe9875 |
| `GRPCOD_E.BSC` | 340 KB | 2,539 | 자재 분류(그룹) 코드 나무 | 2ab6eb0215184f6c |
| `GRPCOD_Z.BSC` | 1.6 MB | 12,125 | 공종 분류(그룹) 코드 나무 | b6c58c548256fdf3 |
판: 머리 날짜 2026-09-01(JDCODE_M·Z·GRPCOD_Z), `호환규정코드(2026_09_01)` = 「2026년 9월 1일 조달청 발표분 반영」 안내 108바이트.
### 2.2 표준시장단가 대형표 (CSTA, DBF `0x06`, 열쇠 AABI1129)
| 파일 | 행 | 비고 |
|---|---|---|
| `실적단가/2026/COSTA.CSTA` = `2026(하…)_표준시장.CSTA` | 4,961 | 설치본(최신 = 하반기와 동일 해시) |
| `실적단가/2026/2026(상…)_표준시장.CSTA` | 4,961 | |
| `실적단가/2025/COSTA.CSTA` 외 2 | 4,921 | |
### 2.3 STBSC 배포 패키지 (암호 ZIP, ZIP 암호 STmate123!@#) — 28개
| 계열 | 개수 | 엔트리(행) | 내용 |
|---|---|---|---|
| 실적단가 2025·2026 | 14 | COST.ST(576~6,348)·CH_NAME.ST(66)·XDET.ST(0)·info.ST | 표준시장·시장시공 단가(조달청·국교·해수부) |
| 노임기계 2025·2026 상·하 | 4 | COST.ST(2,068~2,097)·XDET.ST(2,420~2,503)·CH_NAME.ST(73)·MEM.ST·info.ST | 노임·기계경비 단가 + 중기 구성 |
| 일위대가 2026 토·건·설·전·통 | 5 | COST.ST(416~3,213)·XDET.ST(899~10,182)·CH_NAME.ST(73)·MEM.ST·info.ST | 표준일위대가 대표단가 + 구성 |
| 자재단가 시설공통 2025·2026 | 4 | COST.ST(6,006~6,431)·CH_NAME.ST(72)·Start.ST·info.ST | 시설공통자재 단가 |
### 2.4 제비율 표 (DBF `0x03` 평문, 열쇠 없음) — 44개
`*.JB_R`(일반, 50행×35열 신형/20열 구형) · `*.JB_RA`(표준시장, 50행×20열) · `*.JB_M`·`*.JB_1`(구형). 2007~2026 시행일별. 필드 `RATE_01…RATE_35` = 요율 행렬(간접노무비율·산재·고용·건강·연금·안전관리비·일반관리비·이윤 등, 공사금액 구간 50행).
### 2.5 그 밖
- `EQSYNC.DBF`(System 바로 밑, `0xE6`, 열쇠 EQSN0301) 54행 = 장비 동기화 메타(NAME·SYNC·INS_X).
- `Valid_Xml.vsl` = XML 스키마(평문). `*.Info` = 발표일 안내 글(평문 cp949). `호환규정코드(2026_09_01)` = 안내 글.
## 3. 표별 내용 (필드 뜻 · 대표 행)
### 3.1 JDCODE_{L,M,S,X,Z} — 기초단가·공종 코드 사전
필드 12개: `TYP_1`(대분류: 기초단가/토목공사/건축공사/설비공사) · `TYP_2`(노무·자재·건설기계·기계경비·일위대가·표준시장·기타) · `TYP_`(분류코드) · `JDCODE`(조달 코드, 17자리) · `NAME` · `SIZE`(규격) · `UNIT` · `EQCODE` · `GNCODE` · `TYP_STN`(표준여부 L) · `PSCODE` · `ST_NAME`(표준명).
- L: `L001010101000002 보통인부 / 일반공사 직종 / 인`
- S: `0000010100070000 불도저(무한궤도) / 7 ton / 대 / PSCODE 0101-0007`
- X: `00000101000700000 불도저(무한궤도) / 7 ton / HR`(기계경비)
- Z: `CAA120100019 흙쌓기및헐기 / m3` · `CAA15103000S 작업대차 조립 / 회`(일위대가)
- M: `1015190620704183 백합구근 / 백합구근, 솔나리, 100mm, 개화구 / 포트`
→ 단가(금액)는 없음. 코드↔명칭↔규격↔단위↔조달 JDCODE 의 **사전**. 금액은 CSTA·COST.ST 에.
### 3.2 GRPCOD_{E,Z} — 분류 코드 나무
필드 7개: `TYP_1` · `TYP_`(분류코드) · `CUR_COD`(현재 코드) · `ROT_COD`(부모 코드) · `LEV`(깊이 1~) · `NAME` · `ORD`(차례).
- E: `10 → 1015 → 101519` (자재: 산동식물 > 종자및묘목 > 화초종자및구근…)
- Z: `CA → CAA → CAA1` (토목: 공통공사 > 가설공사(1) > 임시시설)
→ 단가목록·수량산출서의 분류 트리(부모-자식) 원천.
### 3.3 CSTA (COSTA.CSTA) — 표준시장단가 설치본
필드 32개: `CODE`(설치 A코드) · `NAME`·`SIZE`·`UNIT` · `JDCODE`·`BQCODE`·`EQCODE` · 금액 `AAMT1`(합) `MAMT1`(재료) `LAMT1`(노무) `SAMT1`(경비) + 2차 `*AMT2` + 환산 `*_R` + `RATE_L/M/S`(비율) · `TYP_C` · `EDT_DATE`.
- `A09484 P.P마대/쌓기 / 0.024m3 / 개 / A합 921 재19 노902 / JDCODE CAA210901200`
### 3.4 STBSC COST.ST — 배포 단가표
필드 32~33개: `CODE`(배포 W/L코드) · `NAME`·`SIZE`·`UNIT` · `TAMT1`(합) `LAMT1`·`MAMT1`·`SAMT1` · 다단 `AMT_11…61`·`PG_*`(출처 페이지) · `JDCODE` · `CONTCODE` · `ACTTYP` · `SBMOK`(분기호) · `CHK_DATE`. 노임기계·일위대가판은 `RXX`(규격 묶음) 추가.
- 실적 2026상: `W00001 P.P마대/만들기 / 0.024m3 / 개 / T합 2296 노2250 재46 / JDCODE CAA210901100`
- 노임기계 2026하: `L01001 작업반장 / 인 / T 218316`
- 첫 행 `_M_AS_` = 기준월 머릿값(예 `26.01`, `CHK_DATE 20260101`).
### 3.5 STBSC XDET.ST — 구성표(일위대가·중기 산출 근거)
필드 37개: `BDCODE`(상위 묶음) · `CODE`(구성 자원) · `NAME1`·`SIZE1`·`UNIT1` · `QTY1…4`(안별 수량) · `RATE` · `X_QTY1~3`·`X_HAL1~3`(원수량·할증) · `EQCODE` · `PRPT`·`PRIN`·`PROUT`·`KWNGP`(비목 구분) · `EXIST1`.
- 일위대가 토목: `B10001 ← L01006 비계공 / 20.0` · `B10001 ← L01002 보통인부 / 4.0`
→ 프로젝트의 `BDQTY.DBF`(구성표)와 같은 스키마·같은 열쇠(OFOC0603). 일위대가 한 줄이 어떤 자원 몇 개로 이뤄지는지.
### 3.6 STBSC 보조 엔트리
- `CH_NAME.ST`(평문, 66~73행): `SET_CODE`(L/M/S…) · `OLD_NAME` → `NEW_NAME` · `SET_TYP`. 명칭 매칭표(예 `L: 선부→보통인부, 갱부→특별인부, 특수비계공→비계공`). = 자료 업데이트 「명칭 매칭」 단계의 원천.
- `info.ST`(평문): 발표 출처·날짜 안내.
- `MEM.ST`(평문): 중기 규격 묶음(`RXXNM=1/8 * 16/12 * 25/20`) · 직종 묶음(`CONLD=L01048…`).
- `Start.ST`(평문): 자재 가격정보 분류 머리.
### 3.7 SYSINFO.DBF (프로젝트, 열쇠 INFO0301 · 과거 미해독 해소)
`PART`·`NUM`·`LOG`·`CHR`·`DATE` 키-값. 예 `PART=PRG_TYP, CHR=STMATE`. 37 「SYSINFO(암호)」 미확인 해소.
## 4. 표 사이 관계 · 업데이트에서의 쓰임
- **사전 ↔ 금액**: `JDCODE_*`·`GRPCOD_*`(코드·분류, 금액 없음) ↔ `CSTA`·`COST.ST`(금액). 이음 열쇠 = `JDCODE`.
- **배포 → 설치**: STBSC `COST.ST`(배포, JDCODE 있는 6,330행) → 설치 `COSTA.CSTA`(4,961행)로 `JDCODE` 매칭(전수 매칭 확인). 금액은 근사하나 동일하지 않음(설치 시 경비 재배분·환산 추정 — 미검증).
- **구성**: `COST.ST`(대표단가) + `XDET.ST`(구성) = 일위대가/중기 한 벌. 프로젝트에선 `COSTN`(단가) + `BDQTY`(구성)로 대응.
- **자료 업데이트(`wM_Mrg_BSC` 5단계)**: 병합 모듈 `ST_U_Convert.CPM`(`TuM_BSC_M`·`MK_COST_ST`·`MK_XDET_ST`·`MK_CH_NAME_ST`·`Arc_STBSC`). STBSC 를 ZIP 암호로 풀어 `COST.ST`·`XDET.ST`(SIX 복호) 를 읽고, `CH_NAME.ST`(명칭 매칭)·단가·조달코드 기준으로 프로젝트의 COSTN·BDQTY 를 갱신. 5단계 세부 분기(명칭/단가/조달코드 각 매칭 조건)는 함수 본체 전수 복원까진 안 함 — **구조·열쇠·스키마는 확정, 단계별 세부 판정 로직은 부분 확인**.
- **제비율**: `*.JB_R`(일반)·`*.JB_RA`(표준시장) → 프로젝트 `RATE_R`·`RATE_RA` 로 복사(경비·이윤 요율 행렬).
## 5. 우리 프로그램 관점 쓸모 (경쟁사 수준)
- 조달청 발표 체계를 그대로 담음: 기초단가 사전(노무 460·자재 57,580·기계 833·공종 33,927) + 표준시장단가 ~4,961 + 일위대가 구성(토목 10,182행) + 분류 트리 + 시행일별 제비율 44판. **단가 DB 규모·갱신 주기(연 2회 상·하반기, 조달청 발표 즉시)**를 수치로 파악.
- 암호는 **옛 Apollo/SIX 엔진의 고정 알고리즘 + 평문 내장 열쇠 여섯** — 강한 보안 아님(값 무단열람 억제 수준). 데이터 이식·검증엔 불리.
- 설계(현행법 우선) 기준값 확정에 직접 쓰지 않음 — 경쟁사 관찰·대조용 참고. 임의 확정 금지(2장).
## 6. 미확인 (막힌 지점)
- 배포 `COST.ST` → 설치 `CSTA` 금액 차이의 정확한 환산식(예 2307 vs 2296). 열쇠·스키마는 풀림, 변환 수식은 미검증.
- `wM_Mrg_BSC` 5단계의 단계별 판정 분기 전수 로직(병합 모듈 함수 본체 미전수).
- `FORM6511`·`SCOD0301` 열쇠가 여는 실제 표(ST_BSC 밖, 프로젝트 FORM.DBF·조달코드표 추정 — 이번 범위 밖).
## 근거·산출물
- 풀어낸 CSV 전체: `tmp/bsc/csv/`(BSC·CSTA·JB 57개) · `tmp/bsc/csv_stbsc/`(STBSC 엔트리 125개) — git 밖.
- 푸는 코드: `tmp/bsc/sixcrypt.py`(SIX 복호·열쇠) · `decode_all.py` · `decode_stbsc.py` · `inventory.py` — git 밖.
- REA Evidence(Ghidra 12.1.4): `SDECDX50.DLL` 0x10c03ba9·0x10c03cc2·0x10c03c9d · `SDE50.DLL` 0x10005a20·0x10005b39 · `STmate.Cpm` 0x45529c·0x4f10dc·0x5e34e8. 세션 폴더 `tmp/rea_mcp/q_bsc/stage/`. 원본 바이너리·자료 읽기만, 실행 없음.