Can't enter BIOS password containing "!"

(Not an answer to the question as stated in the title, but a way to solve the underlying problem nonetheless).

I think I managed to (mostly) reverse engineer the algorithm that generates the rescue password from the list of past passwords. Unfortunately, I do not own an ASUS board, so I cannot verify whether this correctly predicts new passwords, however running the snippet posted below on dates where the password is known always gives the correct result. If you gives this a try and it does or doesn't work for you, let me know.

Just by looking at the given data in various ways (e.g. by making a table of passwords for a fixed day of the month), one can see a few patterns emerge.

If we label the letters in the password like this: 01234567, then it's easy to see that letters 6 and 7 are uniquely determined by the day of the month (and thus are completely independent of the month or year). For letter 7, simply use the zero-based day of the month as index into the string AAAABLDDBB0LB211C9BAAAAABLDDBB0. Similarly, for letter 6 it's the string LBAL0AL0ADLADLADLADBADBABBAB2AA.

For letter 5, it's also easy to see that in addition to the day of the month, the parity of the month (i.e. its remainder when divided by two) also matters. For odd months, one has to use the reference string BADBOA01AAH1ABBALLBABLBAH1ADL1A, for even months it's A0CAABALBBALBBAH1ABH1ABLABL9ABO.

Letters 2, 3 and 4 are very similar, one just has to use a different lookup table for each month (i.e. each of those letters has twelve lookup tables).

Letter 1 also takes the parity of the year into account. So here one has 24 total lookup tables, 12 for odd years and 12 for even years. Many of these lookup tables actually contain the same letters in the same sequence, they just start at a different point in that sequence. I guess this indicates there's some underlying pattern I haven't quite managed to figure out yet.

Letter 0 is a bit more complex, and I have not yet been able to fully determine a pattern. It seems that depending on the month and year, one of 4 fundamental sequences (OLLAA1AO, ADBA4CAL, AD2AH9AB, AB1A0BB0) is selected and rotated by some specific amount. However, it also seems that the years 2002-2009 follow a different pattern than 2010 and 2011 (in fact, 2010 shows the same behavior as 2008, and 2011 as 2009), so it's very hard to predict how this sequence continues anyway.

Instead, since at this point we already have 7 out of 8 letters determined, and there seem to be only 12 possibilities for the final letter, one could just try to bruteforce the password. If you systematically try out the missing letter by frequency in the 4 sequences mentioned earlier, you should already have a 50% chance of getting the correct password after 2 attempts.

Below is a snippet of Javascript that when run asks you for a date and shows the 12 possible passwords for that date, sorted by likelihood. For today's date (2016-02-28), this would give you X0BLB9BD, with X being one of ABLOD10942CH.

(function() {
    let today = new Date();
    let date = prompt("Enter a date", today.toISOString().substring(0, 10));
    let tables = [
        [["AAAABLDDBB0LB211C9BAAAAABLDDBB0"]],
        [["LBAL0AL0ADLADLADLADBADBABBAB2AA"]],
        [["BADBOA01AAH1ABBALLBABLBAH1ADL1A", "A0CAABALBBALBBAH1ABH1ABLABL9ABO"]],
        [["A49BLA0ODBLA0OD1ALAOD2ALABCA0OA", "BCA0AHBL20A4BLBAOADLBA0AD1ABA", "1ABAA9BLAAACBLA0OD2LAHBD2ALABL2", "ALAB1A0AHB1A0A4BLBAA49BBA0AD1L", "0AD1ABAA91ALAACBLAHACA0AHBD2AAH", "BD2AOAB1AAOAB1A0A491ABA49BBA0A", "BBA0OD1AB0OD1ALAACAALABCA0AHB1A", "0AHBL2AOABLBAOAB1ABOAD1ABA49BAB", "A49BLA0ODBLA0OD1ALAOD2ALABCA0O", "0AHBL2AOABLBAOAB1ABOAD1ABA49BAB", "A49BLA0ODBLA0OD1ALAOD2ALABCA0O", "BCA0AHBL20A4BLBAOADLBA0AD1ABAOD"]],
        [["DA1HABBDAA24ABBLA244A9LLABAA99O", "9LLA2AA9LLBABAACOBAALBACOAALB", "BACOBALBAA10AALDA100AO0DA1HAOOB", "O0DA1HAO00DA1HABBDAA24ABBLA244", "4ABBDA24AA9LLA2AA9LLBABAACOBAAL", "ABAA9OBABBBACOBALBAA10AALDA100", "0AALBA10AAO0DA1HAO00DA1HABBDAA2", "A1HAOBDA114ABBDA24AA9LLA2AA9LLB", "LLA24A9LLLABAA9OBABBBACOBALBAA", "LA24A9LLAABAA9LBABAAACOBALBACC0", "COBABBACOOAALBA10AAA0DA10AO0DD", "DA10AO0DAA1HAO0DA1HHABBDA24ABBL"]],
        [["LA24ABBDAA1HAO0DA1H0AALBA10AAAB", "1HAOBDA1H0AALDA10AAABAACOBABA", "AO0DA10AAALBACOBABAAA9LLA24ABBB", "LBACOBABAAA9LLA24ABBBDA1HAO0DD", "A9LLA24A9BBDA1HAOBDDA10AA0DA1CO", "BDA14ABBDDA10AO0DA1COBALBACOBL", "A1HAO0DA110AALBACOBBABAA9LLA224", "0AALBACOBBABAA9LLA224ABBDA1HAAO", "ABAA9LLAB24ABBDA14AAO0DA1HAO0L", "AO0DA10AAALBACOBABAAA9LLA24ABBB", "LBACOBABBAA9LLA24A9BBDA1HABBDD", "A9LLABAA9BBDA24ABBDDA1HAO0DA1CO"]],
        [["BL4AA20BAAAA2HBA1LDBHBA1ODA90A1", "ODA9BBAOBACBDAOL4AADABLAAA20B", "AA2HBA1LDBHAA1ODA9BA1OLACBBAOLA", "CBDABL4AADABLAAA2HB0AAABHBA1OO", "HAA1ODA9BA10LACBDAOLACLDABLAALD", "AB0AAA2HB0BAABHAA1OOB4AA1OLACA", "10LACBDABBACLDABLAALDA90AAABH90", "BAOBHAA1OOB4AA10LACAA20LACLDA0B", "A1LDAB0AALDA90BAABH9BBAOB4AA1A", "OLA9BBAOLACBDABL4AADABLAAA2HB0A", "AA2HBA1ODBHAA1ODA9BA1OLACBDAOL", "CBDABLAAADAB0AAA2HB0AAABHAA1OOB"], ["BAABHAA1OOB4AA1OLACAA10LACLDA0B", "ACLDAB0AALDA90AAABH90BAOB4AA", "L4AA10LACAA20LACLDAHBA1LDAB0A1O", "DA90BAABH9BBAOB4AA1AOL4AA10LAA", "A20BACLDAHBA1LDA90A1ODA90BAOBAC", "BBAOB4AA1ABL4AA20LAAAA2HBA1LDB", "BA1ODA90B1ODA9BBAOBACBDAOL4AADA", "BLAAA20BAAAA2HBA1LDBHAA1ODA90A1", "OLA9BBAOBACBDABL4AADABLAAA20B0", "A1LDAB0AALDA90BAABH9BBAOB4AA1AO", "L4AA10LACAA20BACLDAHBA1LDA90A1", "DA90BAOBH9BBAOB4AA1AOL4AA20LAAA"]]
    ];

    let match = date.match(/^(\d{4})-(\d{2})-(\d{2})/);
    if (!match) {
        alert("Invalid date: " + date);
        return;
    }

    let [_, y, m, d] = match.map((a,b) => +a)

    let pass = "";
    for (let i = 6; i >= 0; --i) {
        let letters_map = tables[i];
        let year_map = letters_map[y % letters_map.length];
        let month_map = year_map[(m - 1) % year_map.length];
        pass += month_map[d - 1];
    }

    let final_letters = "ABLOD10942CH";

    let output = []
    for (let x = 0; final_letters[x]; ++x)
        output.push(final_letters[x] + pass);

    alert(output.join("\n"));
})();

Proven option
I have always been successful in resetting the BIOS by removing the CMOS battery. I'd recommend removing the power to the laptop and then remove the CMOS battery. The bios battery looks like this and it keeps track of time and BIOS contents.
enter image description here

Wait for a couple of minutes. This action will reset the contents of the BIOS and will let you enter without any passwords.

If you need instructions on how to open your laptop, you can look at the YouTube video here


Alright I got it working again.

I opened the slot at the back where you can see hard drive and some memory sticks. Next to the memory sticks, there are two little things labeled JRST2001 and JRST2002. I first tried to connect one to the other, and then my computer wouldn't even boot, the only thing that light up was the leds next to the keyboard. So I then tried to connect the two "sides" of JRST2001 (there's some kind of line going through it) and same for JRST2002. It then reset the date to 2009-01-01 for which the rescue password is 1BLDABLA. Note that when you enter the rescue password, the computer freezes and you have to manually reboot. Then, since it kept booting into the bios for no apparent reasons, I started changing settings randomly until it worked. And apparently the good setting was the CSM which I needed to enable.


For the record, here's the answer I got from ASUS (emphasis mine):

(I wasn't sure whether this should go in my question or in my answer but I figured people wouldn't want to scroll though that whole thing to get to answer, so I put it here)

Hello Dear Xavier,

Thank you for contacting our ASUS Support.

Following your request, for the computer whos model is G751JY, i understand that you are unable to enter "!" to pass the Bios password and you want to have the rescue password.

Mister Xavier, first of all, i am very sorry to inform you that the BIOS password can be crushed only in our workshops, and this, unfortunately, with a return out of warranty of your computer.

Therefore, to return your computer to diagnose and workshop by ASUS expert, thank you kindly complete the removal form from the following link:

https://eu-rma.asus.com/pick_eu/fr/

Click on the type of product << Notebook >> to complete all required fields.

I invite you to describe as accurately as possible the course "Problem description" so that our technicians can detect and repair the malfunction best of your product.

To validate your pick form, all required fields must be filled and you must check the "Guarantee Agreement provided."

I highly recommend you to click the hyperlink to access the Asus warranty conditions and read them carefully, especially Section 2.2.3.

Once your application is approved, you will receive from us an email with your return agreement number out of warranty and instructions for removal (packing instructions and the general conditions of the After-Sales Service) .

You should have informed a mobile phone number. You will automatically receive information about the status of your repair for each stage.

To track the repair status you can check the box 'I agree to receive SMS information on the status of my repair folder'.

Once the product is received in our service, technicians will make a diagnosis of the failure and will send you a repair estimate.

Then you have the ability to communicate directly to the workshop you wish to continue or not to repair your product.

In case of refusal quote I inform you that the diagnostic fee and the shipping cost will be your responsibility. (~ € 75)

I remain at your disposal, Mr. Xavier, for any additional questions and I wish you a good day.