1

(32 replies, posted in General discussion)

Looks nice, could you write something more?

HandleC2:
ERROR_ACCESS_DENIED - error in ECC logic (too many errors)
ERROR_INVALID_PARAMETER - error in ECC logic (parameters checking for Python function)
ERROR_INVALID_DATA - error in ECC logic (Python function returned not enough data)

The last two error codes shouldn't happen - these are sanity checks.

Under normal circumstances HandleC2 returns either 0 if repair is successful or ERROR_ACCESS_DENIED (5) when it fails.
All return values are the same as system error codes.

All calls to Python functions are enclosed in try/catch blocks (boost::python::error_already_set) with retVal set to ERROR_ACCESS_DENIED - this value is chosen arbitrarily. What do you mean by "comment-out"?

In case sector cannot be repaired (for example because corruption is too big, exception will be thrown, retVal = 5).

HandleC2 can only handle data sectors (data sectors with ECC blocks, mode 2 sectors without ECC are not supported)...

Hmmm. Maybe commit the codes to github branch and I'll debug it locally? Something is not right...

> Btw, python312.dll and boost_python312-vc143-mt-x32-1_87.dll also need to call using LoadLibrary?

No, these DLLs are loaded automatically.

I can trigger this message (Could not find platform independent libraries <prefix>) when PYTHONHOME variable is not set by SetEnvironmentVariableW or when it is set to the wrong path. There are few options left.

1) After InitC2 function is called pause the app under debugger. Use tool like ProcessExplorer and view process environment variables. Check how PYTHONHOME looks like.

2) In the attachment I put a DLL without a call to SetEnvironmentVariableW. Try to call SetEnvironmentVariableW / SetEnvironmentVariableA with path to your Python install directory (C:\Users\xxx\AppData\Local\Programs\Python\Python312-32) before InitC2 function. You can also try setting system wide / user wide PYTHONHOME variable and check which case works.

Maybe there's some problem with config file encoding (by default it expects UTF 16-LE with BOM). Added debugprint (C2Corrector.7z). I have also added testing script which invokes functions from reedsolo.py directly.

Usage:

"c:\Program Files (x86)\Python312-32\python.exe" c2.py

Does it show you any errors?

> Could not find platform independent libraries <prefix>

This is critical problem - I'll test it over the weekend but in the meantime, did you adjust the path in C2Corrector.ini?

Python 3.12 x86: https://www.python.org/ftp/python/3.12. … 3.12.9.exe

32bit DLL in attachment.

Keep in mind, when you pass c2Pointers bitmap, ECC algorithm will only repair bytes which are marked as 1 in C2 bitmap. If the repair is successful bits in c2Repaired bitmap will be set and it's up to you to merge c2Repaired bitmap + write appropriate bytes from sectorData into the image file...

sarami wrote:
reentrant wrote:

Steps:
1) Call InitC2 once in main
2) Call HandleC2 multiple times on each re-read

If possible, please show me the sample code to call these func.

DWORD C2Handler::corruptSectorForP(PC2_CORRECTOR_HANDLE c2HandleBlock, DWORD vectorNo, DWORD errorCount, BOOL enablePointers) {
    if(vectorNo >= 43)
        return ERROR_INVALID_PARAMETER;

    PUCHAR dataBuffer = c2HandleBlock->sectorData;
    
    errorCount = min(errorCount, 26);

    for(DWORD i = 0; i < errorCount; ++i) {
        DWORD dataIndex = userDataOffset + 2 * (43 * i + vectorNo) + 1;

        DEBUGPRINTWO(L"Corrupting P vector: 0x%03X: 0x%02X -> 0x%02X\n", dataIndex, dataBuffer[dataIndex], dataBuffer[dataIndex] + 1);

        ++dataBuffer[dataIndex];

        if(enablePointers && c2HandleBlock->c2Pointers) {
            PUCHAR c2Pointer = &c2HandleBlock->c2Pointers[dataIndex >> 3];
            *c2Pointer |= (0x1 << (dataIndex & 0x7));
        }
    }

    return 0;
}

DWORD C2Handler::corruptSectorForQ(PC2_CORRECTOR_HANDLE c2HandleBlock, DWORD vectorNo, DWORD errorCount, BOOL enablePointers) {
    if(vectorNo >= 26)
        return ERROR_INVALID_PARAMETER;

    PUCHAR dataBuffer = c2HandleBlock->sectorData;
    
    errorCount = min(errorCount, 43);

    for(DWORD i = 0; i < errorCount; ++i) {
        DWORD dataIndex = userDataOffset + 2 * ((43 * vectorNo + 44 * i) % 1118);

        DEBUGPRINTWO(L"Corrupting Q vector: 0x%03X: 0x%02X -> 0x%02X\n", dataIndex, dataBuffer[dataIndex], dataBuffer[dataIndex] + 1);

        ++dataBuffer[dataIndex];

        if(enablePointers && c2HandleBlock->c2Pointers) {
            PUCHAR c2Pointer = &c2HandleBlock->c2Pointers[dataIndex >> 3];
            *c2Pointer |= (0x1 << (dataIndex & 0x7));
        }
    }

    return 0;
}

#include "C2Handler.hpp"

#include <FileOps/FileOps.hpp>

DWORD WINAPI InitC2(PC2_CORRECTOR_INIT c2InitBlock) {
    return C2Handler::initC2(c2InitBlock);
}

DWORD WINAPI HandleC2(PC2_CORRECTOR_HANDLE c2HandleBlock) {
    return C2Handler::handleC2(c2HandleBlock);
}
#ifdef _DEBUG
int main() {
    C2_CORRECTOR_INIT c2InitBlock = {};

    DWORD retVal = InitC2(&c2InitBlock);
    if(!retVal) {
        UCHAR sectorData[2352];
        UCHAR c2Pointers[2352 / 8] = {};
        UCHAR c2Repaired[2352 / 8] = {};

        if(!(retVal = FileOps::readData(L"sector.data.in", sectorData, sizeof(sectorData)))) {
            C2_CORRECTOR_HANDLE c2HandleBlock = {};
            c2HandleBlock.pythonEccP = c2InitBlock.pythonEccP;
            c2HandleBlock.pythonEccQ = c2InitBlock.pythonEccQ;
            c2HandleBlock.sectorData = sectorData;
            c2HandleBlock.c2Pointers = c2Pointers;
            c2HandleBlock.c2Repaired = c2Repaired;

            //C2Handler::corruptSectorForP(&c2HandleBlock, 0, 2, FALSE);
            //retVal = HandleC2(&c2HandleBlock);

            //C2Handler::corruptSectorForP(&c2HandleBlock, 0, 3, TRUE);
            //retVal = HandleC2(&c2HandleBlock);

            C2Handler::corruptSectorForQ(&c2HandleBlock, 0, 2, TRUE);
            retVal = HandleC2(&c2HandleBlock);

            FileOps::writeData(L"sector.data.out", c2HandleBlock.sectorData, sizeof(sectorData));
            FileOps::writeData(L"sector.c2pre.out", c2HandleBlock.c2Pointers, sizeof(c2Pointers));
            FileOps::writeData(L"sector.c2post.out", c2HandleBlock.c2Repaired, sizeof(c2Repaired));
        }
    }

    return retVal ? EXIT_FAILURE : EXIT_SUCCESS;
}
#else
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    return TRUE;
}
#endif
Morlit wrote:

While potentially useful having CDarchive  repair sectors as it extracts them sounds risky.

Potentially yes, I only use it for hardcore cases like fetching more sectors from the rings...

Hi ssjkakaroto, no, it's just a brute-force tool to improve DIC's output...

13

(3,536 replies, posted in General discussion)

Sarami, have a read at this post: http://forum.redump.org/post/125014/#p125014

It'd be nice if you could support this C2 Corrector (plugin support in general, in CDArchive it's optional - app works without it if you delete plugins directory). I think it could greatly enhance C2 error support and save our lasers for a bit longer...

C2Corrector API (Plugins/C2Corrector/C2Corrector.DLL):

#pragma pack(push, 1)
typedef struct _C2_CORRECTOR_INIT {
    PVOID pythonEccP;
    PVOID pythonEccQ;
} C2_CORRECTOR_INIT, *PC2_CORRECTOR_INIT;
#pragma pack(pop)

// InitC2
typedef DWORD (WINAPI *pInitC2)(PC2_CORRECTOR_INIT c2InitBlock);

#pragma pack(push, 1)
typedef struct _C2_CORRECTOR_HANDLE {
    PVOID pythonEccP; // C2_CORRECTOR_INIT.pythonEccP
    PVOID pythonEccQ; // C2_CORRECTOR_INIT.pythonEccQ
    PUCHAR sectorData; // Length: 2352 bytes
    PUCHAR c2Pointers; // Length: 2352 / 8 bytes
    PUCHAR c2Repaired; // Length: 2352 / 8 bytes
} C2_CORRECTOR_HANDLE, *PC2_CORRECTOR_HANDLE;
#pragma pack(pop)

// HandleC2
typedef DWORD (WINAPI *pHandleC2)(PC2_CORRECTOR_HANDLE c2HandleBlock);

Steps:
1) Call InitC2 once in main
2) Call HandleC2 multiple times on each re-read

How it works:
ECC (ECCP / ECCQ) code inside data sector (mode 1 / mode 2) is in fact a Reed-Solomon code.
ECCP = RS(26,24) - difference = 2. It means 1 error can be corrected for a row of 26 bytes (or 2 positions without correcting).
ECCQ = RS(45,43) - difference = 2. It means 1 error can be a corrected for a row of 45 bytes (or 2 positions without correcting).

When you combine the RS algorithm with C2 pointers from the device and use the pointers as erasures it's possible to increase algorithm strength twice (2 errors can be corrected).

C2Corrector does just that - it uses C2 pointers as erasures (positions of invalid bytes) and tries to repair the data. Bytes that were repaired are recorded in c2Repaired buffer. This buffer should be combined with C2 buffer received from the device + appropriate repaired bytes should be replaced with data from sectorData buffer.

That's also how drives work internally. Depending on the manufacturer number of iterations varies (re-read + repair). Some are worse, some are better...

Hi,
New version of CDArchive is out with following new features:
- Automatic sector merging - no need to specify extrsectdir anymore (if specified, sectors will be dumped to the directory anyway)
- Automatic sector checking and repairing (both in the input image as well as those read by the drive) using ECC codes (RSPC). If a specific sector can be repaired (in the image) it is not read from the device.

List of removed dependencies:
- CDmage
- EccEdc

List of added dependencies:
- Python 3.12 - RS library - no C++ code available anywhere

Example command line:
CDArchive.exe --mode=ext --extrdrive=e --extrstart=100 --extrend=200 --extroverread=0 --extrskip=3 --extrdirection=f --extrdiscmode=cd --extrrefcue="d:\Storage\Sin\Sin.cue"

Example output:

Initialized C2 module
Extracting error range forward: 100 - 200
Repaired sector with C2: 150
Repaired sector with C2: 151
Repaired sector with C2: 152
Repaired sector with C2: 153
Repaired sector with C2: 154
Repaired sector with C2: 155
Repaired sector with C2: 156
Range direction result: 0 1

Extracted all sectors

Configuration:
- Install Python 3.12 (exactly this major version)
- Adjust PYTHONHOME variable in config file: Plugins\C2Corrector\C2Corrector.ini
- Copy python312.dll from Python installation directory to Plugins\C2Corrector directory

And that's it - no more tedious merging, fixing, checking...

16

(32 replies, posted in General discussion)

This is used by BWA Builder in the driver: https://learn.microsoft.com/en-us/windo … ncecounter

ULONGLONG performanceFrequency = 0;
ULONGLONG performanceCounter = KeQueryPerformanceCounter(&performanceFrequency);
ULONGLONG ticksMicroSeconds = 1000000 * performanceCounter / performanceFrequency;

I guess on APP side (before DeviceIoControl is made to ASPI driver) the same value is calculated (QueryPerformanceCounter / QueryPerformanceFrequency) and substracted after the call.

There's no driver in DIC but I think it can be emulated purely in user mode just by (QueryPerformanceCounter / QueryPerformanceFrequency) and slow read speed.

Thanks man. It's a nice code but it's not the code I was looking for. Anyway, I have found it elsewhere and I'm preparing a new version of CDArchive which will:
- Remove dependency on CDMage completely
- Remove dependency on edcecc completely
- No merging necessary

18

(32 replies, posted in General discussion)

Which 4 byte enumeration?

I don't know if such rule (valid for CDi) should be applicable to all systems (especially IBM PC)...

Small suggestion: is it possible to emit some metadata describing mastering error of a sector - some info describing what's faulty and how it was corrected - for the purpose of being able to reverse repair operation (to have a possibility of creating unmodified dump)?

Unscrambling has always been a problem for me. It'd be great if both tools were 100% correct about this:
https://github.com/superg/redumper/tree … unscramble

Sarami: any chance you could adapt your unscramber code to pass all of those tests?

Deterous wrote:

It is not for the faint of heart
http://www.wiki.redump.org/index.php?ti … ping_Guide

smile There's one improvement possible - automatic merge of extracted sectors (for dvd it's easy, for cd it's harder as I don't have the code for generating ECC/EDC codes - CDMage has it - probably needs to be ripped somehow)

Do you know where can I find such source code?

EDIT: Loaded CDMage into IDA. There's good news and the bad news. I was able to locate code responsible for checking ECC / EDC  / repairing. The bad news is that it's heavy math (Reed Solomon codes). I was able to find this article by looking after specific magic constants, for example 1118:

https://topic.alibabacloud.com/a/eccedc … 07687.html

Unless someone rips that code from CDMage (hard) or writes it from scratch (hard+++) there's no room for improvement for cd dumping hmm

EDIT2:
For DVDs process can be improved in two ways:
- 2048B sectors can be auto merged into input image file (in the code I have: rangeContext.writeSectorToImage = FALSE, so it's just a matter of setting it to TRUE)
- Read speed can be optimized if I know which 2048B sector is already correct in the input image. If sectors is full of zeroes - I can assume it's corrupted and try to re-read it. Is it safe?

For CDs process can be improved in one way:
- 2352B sectors can be auto merged into input image file (in the code I have: rangeContext.writeSectorToImage = FALSE, so it's just a matter of setting it to TRUE)

Attached newest build with auto-merge enabled...

22

(32 replies, posted in General discussion)

Hi Nemok. I didn't look at this stuff for ages. Nice work, btw. For a reference I am attaching src of dpm module from cd archive app. It's very simple, just a PoC...

PEX2IDE + Windows 10 here = no problems at all. Tested with Plextor 4012 ATA. Are you sure it's the driver problem?

EDIT: After deeper testing it seems these drivers really increase dumping speed... substantially. Thx.

Hi,
There's no limit for number of retries. I usually specified 10 retries not to hammer the drive much...

25

(63 replies, posted in General discussion)

Audio = no. Use DIC for that.